From c9f003c0ab780b72cb7c902201adddf12f51e645 Mon Sep 17 00:00:00 2001 From: Conor Date: Fri, 17 Feb 2023 09:38:46 -0600 Subject: [PATCH 01/61] don't run airbyte ci on schedule (#23202) --- .github/workflows/gradle.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c0180a4e47ec2..29a70bd01f9a2 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -16,8 +16,6 @@ on: - "true" - "false" required: false - schedule: - - cron: "0 */1 * * *" push: branches: - master From 21a7e102183e20d2d4998ea70c2a8fe4eac8921b Mon Sep 17 00:00:00 2001 From: Parker Mossman Date: Fri, 17 Feb 2023 08:14:40 -0800 Subject: [PATCH 02/61] increase init pod copy timeout from 1 minute to 5 minutes (#23158) * increase init pod copy timeout from 1 minute to 5 minutes * add comment explaining --- .../java/io/airbyte/workers/process/KubePodProcess.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/airbyte-commons-worker/src/main/java/io/airbyte/workers/process/KubePodProcess.java b/airbyte-commons-worker/src/main/java/io/airbyte/workers/process/KubePodProcess.java index 78eb3582f65c4..2aa2ebb3f5e52 100644 --- a/airbyte-commons-worker/src/main/java/io/airbyte/workers/process/KubePodProcess.java +++ b/airbyte-commons-worker/src/main/java/io/airbyte/workers/process/KubePodProcess.java @@ -137,7 +137,11 @@ public class KubePodProcess implements KubePod { // init container should fail if no new data copied into the init container within // INIT_RETRY_TIMEOUT_MINUTES private static final double INIT_SLEEP_PERIOD_SECONDS = 0.1; - private static final Duration INIT_RETRY_TIMEOUT_MINUTES = Duration.ofMinutes(1); + + // This timeout was initially 1 minute, but sync pods scheduled on newly-provisioned nodes + // are occasionally not able to start the copy within 1 minute, hence the increase to 5. + private static final Duration INIT_RETRY_TIMEOUT_MINUTES = Duration.ofMinutes(5); + private static final int INIT_RETRY_MAX_ITERATIONS = (int) (INIT_RETRY_TIMEOUT_MINUTES.toSeconds() / INIT_SLEEP_PERIOD_SECONDS); private final KubernetesClient fabricClient; From 2dc839acb8428e53930fce9a09b40f9a16f03d74 Mon Sep 17 00:00:00 2001 From: Charles Date: Fri, 17 Feb 2023 09:31:47 -0800 Subject: [PATCH 03/61] sunset kustomize (#23187) * sunset kustomize * remove build steps that use kustomize * remove k8s kustomize gke-kube-acceptance-tests --- .bumpversion.cfg | 14 +- .github/workflows/gke-kube-test-command.yml | 161 -------- .github/workflows/gradle.yml | 222 ----------- .../gradle-cheatsheet.md | 2 +- kube/README.md | 3 - kube/overlays/dev-integration-test/.env | 101 ----- kube/overlays/dev-integration-test/.secrets | 9 - .../dev-integration-test/kustomization.yaml | 36 -- .../parallelize-worker.yaml | 6 - kube/overlays/dev/.env | 102 ----- kube/overlays/dev/.secrets | 9 - kube/overlays/dev/kustomization.yaml | 33 -- .../overlays/stable-with-resource-limits/.env | 104 ----- .../stable-with-resource-limits/.secrets | 9 - .../kustomization.yaml | 36 -- .../set-resource-limits.yaml | 137 ------- kube/overlays/stable/.env | 102 ----- kube/overlays/stable/.secrets | 9 - kube/overlays/stable/kustomization.yaml | 35 -- kube/resources/admin-service-account.yaml | 25 -- kube/resources/airbyte-minio.yaml | 70 ---- kube/resources/bootloader.yaml | 51 --- kube/resources/connector-builder-server.yaml | 38 -- kube/resources/cron.yaml | 76 ---- kube/resources/db.yaml | 50 --- kube/resources/kustomization.yaml | 18 - kube/resources/pod-sweeper.yaml | 84 ---- kube/resources/secret-gcs-log-creds.yaml | 7 - kube/resources/server.yaml | 225 ----------- kube/resources/temporal.yaml | 116 ------ kube/resources/volume-configs.yaml | 12 - kube/resources/volume-db.yaml | 12 - kube/resources/webapp.yaml | 62 --- kube/resources/worker.yaml | 377 ------------------ tools/bin/acceptance_test_kube.sh | 93 ----- .../acceptance_test_kube_gke.sh | 73 ---- .../postgres-destination.yaml | 47 --- .../postgres-source.yaml | 47 --- 38 files changed, 2 insertions(+), 2611 deletions(-) delete mode 100644 .github/workflows/gke-kube-test-command.yml delete mode 100644 kube/README.md delete mode 100644 kube/overlays/dev-integration-test/.env delete mode 100644 kube/overlays/dev-integration-test/.secrets delete mode 100644 kube/overlays/dev-integration-test/kustomization.yaml delete mode 100644 kube/overlays/dev-integration-test/parallelize-worker.yaml delete mode 100644 kube/overlays/dev/.env delete mode 100644 kube/overlays/dev/.secrets delete mode 100644 kube/overlays/dev/kustomization.yaml delete mode 100644 kube/overlays/stable-with-resource-limits/.env delete mode 100644 kube/overlays/stable-with-resource-limits/.secrets delete mode 100644 kube/overlays/stable-with-resource-limits/kustomization.yaml delete mode 100644 kube/overlays/stable-with-resource-limits/set-resource-limits.yaml delete mode 100644 kube/overlays/stable/.env delete mode 100644 kube/overlays/stable/.secrets delete mode 100644 kube/overlays/stable/kustomization.yaml delete mode 100644 kube/resources/admin-service-account.yaml delete mode 100644 kube/resources/airbyte-minio.yaml delete mode 100644 kube/resources/bootloader.yaml delete mode 100644 kube/resources/connector-builder-server.yaml delete mode 100644 kube/resources/cron.yaml delete mode 100644 kube/resources/db.yaml delete mode 100644 kube/resources/kustomization.yaml delete mode 100644 kube/resources/pod-sweeper.yaml delete mode 100644 kube/resources/secret-gcs-log-creds.yaml delete mode 100644 kube/resources/server.yaml delete mode 100644 kube/resources/temporal.yaml delete mode 100644 kube/resources/volume-configs.yaml delete mode 100644 kube/resources/volume-db.yaml delete mode 100644 kube/resources/webapp.yaml delete mode 100644 kube/resources/worker.yaml delete mode 100755 tools/bin/acceptance_test_kube.sh delete mode 100755 tools/bin/gke-kube-acceptance-test/acceptance_test_kube_gke.sh delete mode 100644 tools/bin/gke-kube-acceptance-test/postgres-destination.yaml delete mode 100644 tools/bin/gke-kube-acceptance-test/postgres-source.yaml diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 7e35c53a3a897..bb841591b5caf 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -3,7 +3,7 @@ current_version = 0.40.32 commit = False tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-[a-z]+)? -serialize = +serialize = {major}.{minor}.{patch} [bumpversion:file:.bumpversion.cfg] @@ -48,18 +48,6 @@ replace = "version": "{new_version}" [bumpversion:file:docs/operator-guides/upgrading-airbyte.md] -[bumpversion:file:kube/overlays/stable-with-resource-limits/.env] -search = AIRBYTE_VERSION={current_version} -replace = AIRBYTE_VERSION={new_version} - -[bumpversion:file:kube/overlays/stable-with-resource-limits/kustomization.yaml] - -[bumpversion:file:kube/overlays/stable/.env] -search = AIRBYTE_VERSION={current_version} -replace = AIRBYTE_VERSION={new_version} - -[bumpversion:file:kube/overlays/stable/kustomization.yaml] - [bumpversion:file:octavia-cli/Dockerfile] [bumpversion:file:octavia-cli/README.md] diff --git a/.github/workflows/gke-kube-test-command.yml b/.github/workflows/gke-kube-test-command.yml deleted file mode 100644 index ff0ed5ecc210a..0000000000000 --- a/.github/workflows/gke-kube-test-command.yml +++ /dev/null @@ -1,161 +0,0 @@ -name: GKE Kube Acceptance Test -on: - schedule: - - cron: "0 0 * * 0" # runs at midnight UTC every Sunday - workflow_dispatch: - inputs: - repo: - description: "Repo to check out code from. Defaults to the main airbyte repo. Set this when building connectors from forked repos." - required: false - default: "airbytehq/airbyte" - gitref: - description: "The git ref to check out from the specified repository." - required: false - default: master - comment-id: - description: "The comment-id of the slash command. Used to update the comment with the status." - required: false - -jobs: - start-gke-kube-acceptance-test-runner: - timeout-minutes: 10 - name: Start GKE Kube Acceptance Test EC2 Runner - runs-on: ubuntu-latest - outputs: - label: ${{ steps.start-ec2-runner.outputs.label }} - ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - repository: ${{ github.event.inputs.repo }} - ref: ${{ github.event.inputs.gitref }} - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Start AWS Runner - id: start-ec2-runner - uses: ./.github/actions/start-aws-runner - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - github-token: ${{ env.PAT }} - gke-kube-acceptance-test: - # In case of self-hosted EC2 errors, removed the `needs` line and switch back to running on ubuntu-latest. - needs: start-gke-kube-acceptance-test-runner # required to start the main job when the runner is ready - runs-on: ${{ needs.start-gke-kube-acceptance-test-runner.outputs.label }} # run the job on the newly created runner - name: GKE Acceptance Tests (Kube) - timeout-minutes: 90 - steps: - - name: Link comment to workflow run - if: github.event.inputs.comment-id - uses: peter-evans/create-or-update-comment@v1 - with: - comment-id: ${{ github.event.inputs.comment-id || ""}} - body: | - > :clock2: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} - - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - repository: ${{ github.event.inputs.repo || "airbytehq/airbyte" }} - ref: ${{ github.event.inputs.gitref || "master" }} - - - uses: actions/setup-java@v3 - with: - distribution: "zulu" - java-version: "17" - - - uses: actions/setup-node@v3 - with: - node-version: "lts/*" - - - name: Fix EC-2 Runner - run: | - mkdir -p /home/runner - - - name: Install socat (required for port forwarding) - run: | - sudo apt-get update - sudo apt-get install socat - - - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@v0 - with: - project_id: ${{ secrets.GKE_TEST_PROJECT_ID }} - service_account_key: ${{ secrets.GKE_TEST_SA_KEY }} - export_default_credentials: true - - - name: Get GKE credentials - uses: google-github-actions/get-gke-credentials@main - with: - project_id: ${{ secrets.GKE_TEST_PROJECT_ID }} - credentials: ${{ secrets.GKE_TEST_SA_KEY }} - cluster_name: kube-acceptance-test-cluster - location: us-central1-c - - - name: Install kubectl - run: |- - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl - - - name: Run End-to-End Acceptance Tests on GKE - id: gke-kube-test - env: - USER: root - HOME: /home/runner - DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} - DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }} - ACTION_RUN_ID: ${{github.run_id}} - run: | - ./tools/bin/gke-kube-acceptance-test/acceptance_test_kube_gke.sh - - - name: Add Success Comment - if: github.event.inputs.comment-id && success() - uses: peter-evans/create-or-update-comment@v1 - with: - comment-id: ${{ github.event.inputs.comment-id }} - body: | - > :white_check_mark: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} - - name: Add Failure Comment - if: github.event.inputs.comment-id && !success() - uses: peter-evans/create-or-update-comment@v1 - with: - comment-id: ${{ github.event.inputs.comment-id }} - body: | - > :x: https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} - # In case of self-hosted EC2 errors, remove this block. - stop-gke-kube-acceptance-test-runner: - name: Stop GKE Kube Acceptance Test EC2 Runner - timeout-minutes: 10 - needs: - - start-gke-kube-acceptance-test-runner # required to get output from the start-runner job - - gke-kube-acceptance-test # required to wait when the main job is done - runs-on: ubuntu-latest - if: ${{ always() }} - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-2 - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - repository: ${{ github.event.inputs.repo }} - ref: ${{ github.event.inputs.gitref }} - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Stop EC2 runner - uses: supertopher/ec2-github-runner@base64v1.0.10 - with: - mode: stop - github-token: ${{ env.PAT }} - label: ${{ needs.start-gke-kube-acceptance-test-runner.outputs.label }} - ec2-instance-id: ${{ needs.start-gke-kube-acceptance-test-runner.outputs.ec2-instance-id }} diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 29a70bd01f9a2..a1c63f5f4b623 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -831,228 +831,6 @@ jobs: label: ${{ needs.start-platform-build-runner.outputs.label }} ec2-instance-id: ${{ needs.start-platform-build-runner.outputs.ec2-instance-id }} - ## Kube Acceptance Tests - # Docker acceptance tests run as part of the build job. - # In case of self-hosted EC2 errors, remove this block. - start-kube-acceptance-test-runner: - name: "Platform: Start Kube Acceptance Test Runner" - needs: - - changes - # Because scheduled builds on master require us to skip the changes job. Use always() to force this to run on master. - if: needs.changes.outputs.backend == 'true' || needs.changes.outputs.build == 'true' || (always() && github.ref == 'refs/heads/master') - timeout-minutes: 10 - runs-on: ubuntu-latest - outputs: - label: ${{ steps.start-ec2-runner.outputs.label }} - ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Start AWS Runner - id: start-ec2-runner - uses: ./.github/actions/start-aws-runner - with: - # github-self-hosted-runner-ubuntu-20-with-150gdisk-docker-20.10.7-and-socat - ec2-image-id: ami-0c1a9bc22624339d8 - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - github-token: ${{ env.PAT }} - kube-acceptance-test: - name: "Platform: Acceptance Tests (Kube)" - # In case of self-hosted EC2 errors, removed the `needs` line and switch back to running on ubuntu-latest. - needs: start-kube-acceptance-test-runner # required to start the main job when the runner is ready - runs-on: ${{ needs.start-kube-acceptance-test-runner.outputs.label }} # run the job on the newly created runner - environment: more-secrets - timeout-minutes: 40 - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - - - name: Cache Build Artifacts - uses: ./.github/actions/cache-build-artifacts - with: - cache-key: ${{ secrets.CACHE_VERSION }} - cache-python: "false" - - - uses: actions/setup-java@v3 - with: - distribution: "zulu" - java-version: "17" - - - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - - name: Install unzip - shell: bash - run: sudo apt-get update && sudo apt-get install -y unzip - - - uses: azure/setup-helm@v3 - with: - version: "latest" - token: ${{ secrets.GITHUB_TOKEN }} - id: install - - - name: Fix EC-2 Runner - run: | - mkdir -p /home/runner - - - name: Set up CI Gradle Properties - run: | - mkdir -p ~/.gradle/ - cat > ~/.gradle/gradle.properties < /tmp/kind-config.yaml < /tmp/kubernetes_logs/server.txt; } - pod_sweeper_logs () { kubectl logs deployment.apps/airbyte-pod-sweeper > /tmp/kubernetes_logs/pod_sweeper.txt; } - worker_logs () { kubectl logs deployment.apps/airbyte-worker > /tmp/kubernetes_logs/worker.txt; } - db_logs () { kubectl logs deployment.apps/airbyte-db > /tmp/kubernetes_logs/db.txt; } - temporal_logs () { kubectl logs deployment.apps/airbyte-temporal > /tmp/kubernetes_logs/temporal.txt; } - describe_pods () { kubectl describe pods > /tmp/kubernetes_logs/describe_pods.txt; } - describe_nodes () { kubectl describe nodes > /tmp/kubernetes_logs/describe_nodes.txt; } - write_all_logs () { - server_logs; - worker_logs; - db_logs; - temporal_logs; - pod_sweeper_logs; - describe_nodes; - describe_pods; - } -# Uncomment for debugging. Warning, this is verbose. - # trap "mkdir -p /tmp/kubernetes_logs && write_all_logs" EXIT -fi - -kubectl port-forward svc/airbyte-server-svc 8001:8001 & - -echo "Running worker integration tests..." -SUB_BUILD=PLATFORM ./gradlew :airbyte-workers:integrationTest --scan - -echo "Printing system disk usage..." -df -h - -echo "Printing docker disk usage..." -docker system df - -if [ -n "$CI" ]; then - echo "Pruning all images..." - docker image prune --all --force - - echo "Printing system disk usage after pruning..." - df -h - - echo "Printing docker disk usage after pruning..." - docker system df -fi - -echo "Running e2e tests via gradle..." -KUBE=true SUB_BUILD=PLATFORM USE_EXTERNAL_DEPLOYMENT=true ./gradlew :airbyte-tests:acceptanceTests --scan diff --git a/tools/bin/gke-kube-acceptance-test/acceptance_test_kube_gke.sh b/tools/bin/gke-kube-acceptance-test/acceptance_test_kube_gke.sh deleted file mode 100755 index f7f3d50f1504c..0000000000000 --- a/tools/bin/gke-kube-acceptance-test/acceptance_test_kube_gke.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash - -set -e - -. tools/lib/lib.sh - -assert_root -kubectl --help - -NAMESPACE=$(openssl rand -hex 12) -echo "Namespace" $NAMESPACE - -TAG=$(openssl rand -hex 12) -echo "Tag" $TAG - -docker login -u "$DOCKER_HUB_USERNAME" -p "$DOCKER_HUB_PASSWORD" -VERSION=$TAG ./gradlew build -VERSION=$TAG docker compose -f docker-compose.build.yaml push - -# For running on Mac -#sed -i .bak 's/default/'$NAMESPACE'/g' kube/overlays/dev/kustomization.yaml -#sed -i .bak 's/dev/'$TAG'/g' kube/overlays/dev/kustomization.yaml - -sed -i 's/default/'$NAMESPACE'/g' kube/overlays/dev/kustomization.yaml -sed -i 's/dev/'$TAG'/g' kube/overlays/dev/kustomization.yaml - -kubectl create namespace $NAMESPACE -kubectl config set-context --current --namespace=$NAMESPACE - -kubectl apply -k kube/overlays/dev --namespace=$NAMESPACE -kubectl apply -f tools/bin/gke-kube-acceptance-test/postgres-source.yaml --namespace=$NAMESPACE -kubectl apply -f tools/bin/gke-kube-acceptance-test/postgres-destination.yaml --namespace=$NAMESPACE - -sleep 180s - -function findAndDeleteTag () { - if [ $(curl --fail -LI --request GET 'https://hub.docker.com/v2/repositories/airbyte/'$1'/tags/'$TAG'/' --header 'Authorization: JWT '$2'' -o /dev/null -w '%{http_code}\n' -s) == "200" ]; - then - echo "FOUND TAG" $TAG "in repository" $1 ",DELETING IT" - curl --request DELETE 'https://hub.docker.com/v2/repositories/airbyte/'$1'/tags/'$TAG'/' --header 'Authorization: JWT '$2''; - else - echo "NOT FOUND TAG" $TAG "in repository" $1; - fi -} - -function cleanUpImages () { - TOKEN=$(curl --request POST 'https://hub.docker.com/v2/users/login/' --header 'Content-Type: application/json' --data-raw '{"username":"'$DOCKER_HUB_USERNAME'","password":"'$DOCKER_HUB_PASSWORD'"}' | jq '.token') - TOKEN="${TOKEN%\"}" - TOKEN="${TOKEN#\"}" - - findAndDeleteTag "init" $TOKEN - findAndDeleteTag "db" $TOKEN - findAndDeleteTag "seed" $TOKEN - findAndDeleteTag "scheduler" $TOKEN - findAndDeleteTag "server" $TOKEN - findAndDeleteTag "webapp" $TOKEN - findAndDeleteTag "migration" $TOKEN - findAndDeleteTag "cron" $TOKEN -} - -trap "cleanUpImages && kubectl delete namespaces $NAMESPACE --grace-period=0 --force" EXIT - -kubectl port-forward svc/airbyte-server-svc 8001:8001 --namespace=$NAMESPACE & - -kubectl port-forward svc/postgres-source-svc 2000:5432 --namespace=$NAMESPACE & - -kubectl port-forward svc/postgres-destination-svc 4000:5432 --namespace=$NAMESPACE & - -sleep 10s - -echo "Running e2e tests via gradle..." -KUBE=true IS_GKE=true SUB_BUILD=PLATFORM USE_EXTERNAL_DEPLOYMENT=true ./gradlew :airbyte-tests:acceptanceTests --scan -i - diff --git a/tools/bin/gke-kube-acceptance-test/postgres-destination.yaml b/tools/bin/gke-kube-acceptance-test/postgres-destination.yaml deleted file mode 100644 index 22f9ac19b4769..0000000000000 --- a/tools/bin/gke-kube-acceptance-test/postgres-destination.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: postgres-destination-config - labels: - app: postgres-destination -data: - POSTGRES_DB: postgresdb - POSTGRES_USER: postgresadmin - POSTGRES_PASSWORD: admin123 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres-destination -spec: - replicas: 1 - selector: - matchLabels: - app: postgres-destination - template: - metadata: - labels: - app: postgres-destination - spec: - containers: - - name: postgres-destination - image: postgres:13-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - envFrom: - - configMapRef: - name: postgres-destination-config ---- -apiVersion: v1 -kind: Service -metadata: - name: postgres-destination-svc - labels: - app: postgres-destination -spec: - type: ClusterIP - ports: - - port: 5432 - selector: - app: postgres-destination diff --git a/tools/bin/gke-kube-acceptance-test/postgres-source.yaml b/tools/bin/gke-kube-acceptance-test/postgres-source.yaml deleted file mode 100644 index ee7e49d9c2f15..0000000000000 --- a/tools/bin/gke-kube-acceptance-test/postgres-source.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: postgres-source-config - labels: - app: postgres-source -data: - POSTGRES_DB: postgresdb - POSTGRES_USER: postgresadmin - POSTGRES_PASSWORD: admin123 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres-source -spec: - replicas: 1 - selector: - matchLabels: - app: postgres-source - template: - metadata: - labels: - app: postgres-source - spec: - containers: - - name: postgres-source - image: debezium/postgres:13-alpine - imagePullPolicy: "IfNotPresent" - ports: - - containerPort: 5432 - envFrom: - - configMapRef: - name: postgres-source-config ---- -apiVersion: v1 -kind: Service -metadata: - name: postgres-source-svc - labels: - app: postgres-source -spec: - type: ClusterIP - ports: - - port: 5432 - selector: - app: postgres-source From feadfd4ebf42150a01ee5dc4b611db0175e1513e Mon Sep 17 00:00:00 2001 From: Topher Lubaway Date: Sat, 18 Feb 2023 15:37:51 -0600 Subject: [PATCH 04/61] Working replacement script for docker (#23227) * Working replacement script for docker * Working debugging line * rename start script and add download files to gitignore * add args and download only option * Made flags cleaner and more cleanup i've never used this flag pattern, its much easier than my usual way * warn about a sharp edge * Don't run when we don't know a command * better help spacing * add flags.yml --------- Co-authored-by: cpdeethree Co-authored-by: Conor --- .gitignore | 6 ++ run-ab-platform.sh | 164 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100755 run-ab-platform.sh diff --git a/.gitignore b/.gitignore index a6e0049c2f687..ed73a6a9f4c82 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,9 @@ charts/**/charts # Datadog dd-java-agent.jar + +# Files needed to run airbyte-platform that are downloaded on-the-fly via run-ab-platform.sh +docker-compose.yaml +.env +.env.dev +flags.yml diff --git a/run-ab-platform.sh b/run-ab-platform.sh new file mode 100755 index 0000000000000..773e80f6a241d --- /dev/null +++ b/run-ab-platform.sh @@ -0,0 +1,164 @@ +# Run away from anything even a little scary +set -o nounset # -u exit if a variable is not set +set -o errexit # -f exit for any command failure + + +# text color escape codes (please note \033 == \e but OSX doesn't respect the \e) +blue_text='\033[94m' +red_text='\033[31m' +default_text='\033[39m' + +# set -x/xtrace uses a Sony PS4 for more info +PS4="$blue_text""${BASH_SOURCE}:${LINENO}: ""$default_text" + +############################################################ +# Help # +############################################################ +Help() +{ + # Display Help + echo "This Script will download the necessary files for running docker compose" + echo "It will also run docker compose up" + echo "Take Warning! These assets may become stale over time!" + echo + # $0 is the currently running program + echo "Syntax: $0" + echo "options:" + echo " -d --download Only download files - don't run docker compose" + echo " -r --refresh ${red_text}DELETE${default_text} existing assets and re-download new ones" + echo " -h --help Print this Help." + echo " -x --debug Verbose mode." + echo +} + +########## Declare assets care about ########## +docker_compose_yaml="docker-compose.yaml" + dot_env=".env" + dot_env_dev=".env.dev" + flags="flags.yml" +# any string is an array to POSIX shell. Space seperates values +all_files="$docker_compose_yaml $dot_env $dot_env_dev $flags" +base_github_url="https://raw.githubusercontent.com/airbytehq/airbyte-platform/main/" + +############################################################ +# Download # +############################################################ +Download() +{ + ########## Check if we already have the assets we are looking for ########## + for file in $all_files; do + if test -f $file; then + # Check if the assets are old. A possibly sharp corner + if test $(find $file -type f -mtime +60 > /dev/null); then + echo "$red_text""Warning your $file may be stale!""$default_text" + echo "$red_text""rm $file to refresh!""$default_text" + else + echo "$blue_text""found $file locally!""$default_text" + fi + else + echo "$blue_text""Downloading $file""$default_text" + curl --location\ + --fail\ + --silent\ + --show-error \ + ${base_github_url}${file} > $file + fi + done +} + +DeleteLocalAssets() +{ + for file in $all_files; do + echo "$blue_text""Attempting to delete $file!""$default_text" + if test -f $file; then + rm $file && echo "It's gone!" + else + echo "$file not found locally. Nothing to delete." + fi + done +} + + +# $0 is the currently running program (this file) +this_file_directory=$(dirname $0) +# Run this from the / directory because we assume relative paths +cd ${this_file_directory} + + +for argument in $@; do + case $argument in + -d | --download) + Download + exit + ;; + -r | --refresh) + DeleteLocalAssets + exit + ;; + -h | --help) + Help + exit + ;; + -x | --debug) + set -o xtrace # -x display every line before execution; enables PS4 + ;; + *) + echo "$argument is not a known command." + echo + Help + exit + ;; + esac + shift +done + + +########## Pointless Banner for street cred ########## +# Make sure the console is huuuge +if test $(tput cols) -ge 64; then + # Make it green! + echo "\033[32m" + echo " █████╗ ██╗██████╗ ██████╗ ██╗ ██╗████████╗███████╗" + echo "██╔══██╗██║██╔══██╗██╔══██╗╚██╗ ██╔╝╚══██╔══╝██╔════╝" + echo "███████║██║██████╔╝██████╔╝ ╚████╔╝ ██║ █████╗ " + echo "██╔══██║██║██╔══██╗██╔══██╗ ╚██╔╝ ██║ ██╔══╝ " + echo "██║ ██║██║██║ ██║██████╔╝ ██║ ██║ ███████╗" + echo "╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝ ╚══════╝" + echo " Move Data" + # Make it less green + echo "\033[0m" + sleep 1 +fi + +########## Dependency Check ########## +if ! which -s docker-compose; then + echo "$red_text""docker compose not found! please install docker compose!""$default_text" +fi + +Download + +########## Source Envionmental Variables ########## + +for file in $dot_env $dot_env_dev; do + echo "$blue_text""Loading Shell Variables from $file...""$default_text" + source $file +done + + +########## Start Docker ########## + +echo +echo "$blue_text""Starting Docker Compose""$default_text" + +docker-compose up + +# $? is the exit code of the last command. So here: docker-compose up +if test $? -ne 0; then + echo "$red_text""Docker compose failed. If you are seeing container conflicts""$default_text" + echo "$red_text""please consider removing old containers""$default_text" +fi + +########## Ending Docker ########## +docker-compose down + +echo "$blue_text""Starting Docker Compose""$default_text" From 7953c45a093345abfed6cf03fe4455c89b336689 Mon Sep 17 00:00:00 2001 From: Conor Date: Sun, 19 Feb 2023 09:42:08 -0600 Subject: [PATCH 05/61] delete platform code and workflows (#23214) * delete platform code and workflows * delete more platform workflows * sunset kustomize (#23187) * sunset kustomize * remove build steps that use kustomize * remove k8s kustomize gke-kube-acceptance-tests * delete docker-compose files * remove platform from check_images_exist.sh * Working replacement script for docker * rename start script and add download files to gitignore * add args and download only option * integration test downloads docker compose files * remove helm charts * remove more platform files * add flags.yml * use version from gradle.properties instead of .env * Working replacement script for docker (#23227) * Working replacement script for docker * Working debugging line * rename start script and add download files to gitignore * add args and download only option * Made flags cleaner and more cleanup i've never used this flag pattern, its much easier than my usual way * warn about a sharp edge * Don't run when we don't know a command * better help spacing * add flags.yml --------- Co-authored-by: cpdeethree Co-authored-by: Conor * remove more-secrets env --------- Co-authored-by: Charles Co-authored-by: Topher Lubaway --- .env | 117 - .env.dev | 38 - .../actions/build-and-push-branch/action.yml | 33 - .github/actions/build-branch/action.yml | 42 - .github/workflows/build-report.yml | 1 - .github/workflows/doc-link-check.yml | 1 - .github/workflows/gradle.yml | 736 +- .github/workflows/publish-command.yml | 1 - .../workflows/publish-connector-command.yml | 1 - .github/workflows/publish-helm-charts.yml | 137 - .github/workflows/publish-oss-for-cloud.yml | 190 - .github/workflows/release-airbyte-os.yml | 7 +- .github/workflows/run-performance-test.yml | 56 - .github/workflows/test-command.yml | 1 - .../workflows/test-performance-command.yml | 3 +- airbyte-bootloader/Dockerfile | 14 - airbyte-bootloader/Readme.md | 6 - airbyte-bootloader/build.gradle | 76 - airbyte-bootloader/gradle.properties | 1 - .../io/airbyte/bootloader/Application.java | 30 - .../io/airbyte/bootloader/Bootloader.java | 244 - .../bootloader/DefaultPostLoadExecutor.java | 57 - .../bootloader/ProtocolVersionChecker.java | 220 - .../io/airbyte/bootloader/SecretMigrator.java | 155 - .../config/ApplicationBeanFactory.java | 74 - .../config/DatabaseBeanFactory.java | 130 - .../config/SecretPersistenceBeanFactory.java | 110 - .../src/main/resources/application.yml | 121 - .../resources/banner/attention-banner.txt | 13 - .../src/main/resources/micronaut-banner.txt | 8 - .../io/airbyte/bootloader/BootloaderTest.java | 417 - .../DefaultPostLoadExecutorTest.java | 79 - .../ProtocolVersionCheckerTest.java | 360 - .../bootloader/SecretMigratorTest.java | 184 - airbyte-commons-server/build.gradle | 67 - .../airbyte/commons/server/RequestLogger.java | 163 - .../commons/server/ServerConstants.java | 11 - .../server/converters/ApiPojoConverters.java | 319 - .../converters/CatalogDiffConverters.java | 81 - .../converters/ConfigurationUpdate.java | 79 - .../server/converters/JobConverter.java | 261 - .../converters/NotificationConverter.java | 51 - .../converters/OauthModelConverter.java | 63 - .../converters/OperationsConverter.java | 161 - .../server/converters/SpecFetcher.java | 20 - .../converters/WorkflowStateConverter.java | 18 - .../WorkspaceWebhookConfigsConverter.java | 84 - .../ApplicationErrorKnownException.java | 22 - .../errors/BadObjectSchemaKnownException.java | 22 - .../errors/ConnectFailureKnownException.java | 22 - .../errors/IdNotFoundExceptionMapper.java | 35 - .../errors/IdNotFoundKnownException.java | 50 - .../errors/InternalServerKnownException.java | 22 - .../errors/InvalidInputExceptionMapper.java | 47 - .../errors/InvalidJsonExceptionMapper.java | 23 - .../InvalidJsonInputExceptionMapper.java | 25 - .../commons/server/errors/KnownException.java | 42 - .../server/errors/KnownExceptionMapper.java | 32 - .../errors/NotFoundExceptionMapper.java | 32 - .../errors/UncaughtExceptionMapper.java | 30 - .../UnsupportedProtocolVersionException.java | 25 - .../errors/ValueConflictKnownException.java | 22 - .../server/handlers/AttemptHandler.java | 81 - .../server/handlers/ConnectionsHandler.java | 609 - .../DestinationDefinitionsHandler.java | 334 - .../server/handlers/DestinationHandler.java | 329 - .../server/handlers/HealthCheckHandler.java | 25 - .../server/handlers/JobHistoryHandler.java | 305 - .../commons/server/handlers/LogsHandler.java | 55 - .../commons/server/handlers/OAuthHandler.java | 364 - .../server/handlers/OpenApiConfigHandler.java | 32 - .../server/handlers/OperationsHandler.java | 195 - .../server/handlers/SchedulerHandler.java | 549 - .../handlers/SourceDefinitionsHandler.java | 335 - .../server/handlers/SourceHandler.java | 370 - .../commons/server/handlers/StateHandler.java | 43 - .../WebBackendCheckUpdatesHandler.java | 115 - .../WebBackendConnectionsHandler.java | 794 - .../WebBackendGeographiesHandler.java | 36 - .../server/handlers/WorkspacesHandler.java | 314 - .../handlers/helpers/CatalogConverter.java | 315 - .../handlers/helpers/ConnectionMatcher.java | 52 - .../helpers/ConnectionScheduleHelper.java | 97 - .../handlers/helpers/DestinationMatcher.java | 54 - .../server/handlers/helpers/Matchable.java | 12 - .../handlers/helpers/OAuthPathExtractor.java | 40 - .../handlers/helpers/SourceMatcher.java | 51 - .../DefaultSynchronousSchedulerClient.java | 282 - .../commons/server/scheduler/EventRunner.java | 33 - .../scheduler/SynchronousJobMetadata.java | 147 - .../server/scheduler/SynchronousResponse.java | 89 - .../scheduler/SynchronousSchedulerClient.java | 42 - .../server/scheduler/TemporalEventRunner.java | 62 - .../server/services/AirbyteGithubStore.java | 91 - .../commons/server/RequestLoggerTest.java | 245 - .../converters/CatalogConverterTest.java | 130 - .../converters/CatalogDiffConvertersTest.java | 24 - .../converters/ConfigurationUpdateTest.java | 112 - .../server/converters/JobConverterTest.java | 288 - .../converters/OauthModelConverterTest.java | 69 - .../server/handlers/AttemptHandlerTest.java | 135 - .../ConnectionSchedulerHelperTest.java | 681 - .../handlers/ConnectionsHandlerTest.java | 1377 -- .../DestinationDefinitionsHandlerTest.java | 673 - .../handlers/DestinationHandlerTest.java | 370 - .../handlers/HealthCheckHandlerTest.java | 35 - .../handlers/JobHistoryHandlerTest.java | 456 - .../server/handlers/LogsHandlerTest.java | 49 - .../server/handlers/OAuthHandlerTest.java | 235 - .../handlers/OpenApiConfigHandlerTest.java | 23 - .../handlers/OperationsHandlerTest.java | 386 - .../server/handlers/SchedulerHandlerTest.java | 1248 -- .../SourceDefinitionsHandlerTest.java | 622 - .../server/handlers/SourceHandlerTest.java | 402 - .../server/handlers/StateHandlerTest.java | 139 - .../WebBackendCheckUpdatesHandlerTest.java | 190 - .../WebBackendConnectionsHandlerTest.java | 1396 -- .../WebBackendGeographiesHandlerTest.java | 43 - .../handlers/WorkspacesHandlerTest.java | 590 - .../helper/OAuthPathExtractorTest.java | 44 - .../server/helpers/ConnectionHelpers.java | 401 - .../ConnectorSpecificationHelpers.java | 33 - .../helpers/DestinationDefinitionHelpers.java | 21 - .../server/helpers/DestinationHelpers.java | 69 - .../helpers/SourceDefinitionHelpers.java | 21 - .../commons/server/helpers/SourceHelpers.java | 66 - ...DefaultSynchronousSchedulerClientTest.java | 256 - .../services/AirbyteGithubStoreTest.java | 161 - .../test/resources/icons/test-destination.svg | 3 - .../src/test/resources/icons/test-source.svg | 3 - .../resources/json/TestImplementation.json | 4 - .../resources/json/TestSpecification.json | 19 - .../03a4c904-c91d-447f-ab59-27a43b52c2fd.gz | Bin 5774 -> 0 bytes .../4e00862d-5484-4f50-9860-f3bbb4317397.json | 16 - .../5434615d-a3b7-4351-bc6b-a9a695555a30.json | 8 - .../28ffee2b-372a-4f72-9b95-8ed56a8b99c5.json | 14 - .../e48cae1a-1f5c-42cc-9ec1-a44ff7fb4969.json | 14 - .../22f6c74f-5699-40ff-833c-4a879ea40133.json | 12 - .../25c5221d-dce2-4163-ade9-739ef790f503.json | 12 - .../424892c4-daac-4491-b35d-c6688ba547ba.json | 12 - .../8be1cf83-fde1-477f-a4ad-318d23c9f3c6.json | 12 - .../a625d593-bba5-4a1c-a53d-2d246268a816.json | 12 - .../af7c921e-5892-4ff2-b6c1-4a5ab258fb7e.json | 12 - .../f7a7d195-377f-cf5b-70a5-be6b819019dc.json | 12 - .../00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c.json | 11 - .../2470e835-feaf-4db6-96f3-70fd645acc77.json | 11 - .../2af123bf-0aaf-4e0d-9784-cb497f23741a.json | 11 - .../396e4ca3-8a97-4b85-aa4e-c9d8c2d5f992.json | 11 - .../41375467-61ae-4204-8e38-e2b8b7365f23.json | 11 - .../435bb9a5-7887-4809-aa58-28c27df0d7ad.json | 11 - .../445831eb-78db-4b1f-8f1f-0d96ad8739e2.json | 11 - .../4eb22946-2a79-4d20-a3e6-effd234613c3.json | 11 - .../57eb1576-8f52-463d-beb6-2e107cdf571d.json | 11 - .../59f1e50a-331f-4f09-b3e8-2e8d4d355f44.json | 11 - .../68e63de2-bb83-4c7e-93fa-a8a9051e3993.json | 11 - .../71607ba1-c0ac-4799-8049-7f4b90dd50f7.json | 11 - .../778daa7c-feaf-4db6-96f3-70fd645acc77.json | 11 - .../859e501d-2b67-471f-91bb-1c801414d28f.json | 11 - .../9e0556f4-69df-4522-a3fb-03264d36b348.json | 11 - .../9fed261d-d107-47fd-8c8b-323023db6e20.json | 11 - .../aea2fd0d-377d-465e-86c0-4fdc4f688e51.json | 11 - .../b03a9f3e-22a5-11eb-adc1-0242ac120002.json | 11 - .../b1892b11-788d-44bd-b9ec-3a436f7b54ce.json | 11 - .../b5ea17b1-f170-46dc-bc31-cc744ca984c1.json | 11 - .../cd42861b-01fc-4658-a8ab-5d11d0510f01.json | 11 - .../d2147be5-fa36-4936-977e-f031affa5895.json | 11 - .../d29764f8-80d7-4dd7-acbe-1a42005ee5aa.json | 11 - .../d8313939-3782-41b0-be29-b3ca20d8dd3a.json | 11 - .../decd338e-5647-4c0b-adf4-da0e75f5a750.json | 11 - .../e094cb9a-26de-4645-8761-65c0c425d1de.json | 11 - .../e7778cfc-e97c-4458-9ecb-b4f2bba8946c.json | 11 - .../e87ffa8e-a3b5-f69c-9076-6011339de1f6.json | 11 - .../eaf50f04-21dd-4620-913b-2a83f5635227.json | 11 - .../ec4b9503-13cb-48ab-a4ab-6ade4be46567.json | 11 - .../ed799e2b-2158-4c66-8da4-b40fe63bc72a.json | 11 - .../ef69ef6e-aa7f-4af1-a01d-ef775033524e.json | 11 - .../fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87.json | 11 - .../49dae3f0-158b-4737-b6e4-0eed77d4b74e.json | 45 - .../a294256f-1abe-4837-925f-91602c7207b4.json | 45 - .../49dae3f0-158b-4737-b6e4-0eed77d4b74e.json | 1 - .../a294256f-1abe-4837-925f-91602c7207b4.json | 1 - .../5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6.json | 11 - .../src/test/resources/migration/schema.sql | 82 - airbyte-connector-builder-server/.coveragerc | 3 - .../.dockerignore | 4 - airbyte-connector-builder-server/.gitignore | 3 - .../.python-version | 1 - airbyte-connector-builder-server/CDK_VERSION | 1 - airbyte-connector-builder-server/CHANGELOG.md | 0 airbyte-connector-builder-server/Dockerfile | 14 - airbyte-connector-builder-server/README.md | 30 - airbyte-connector-builder-server/build.gradle | 61 - .../connector_builder/__init__.py | 3 - .../connector_builder/entrypoint.py | 29 - .../generated/apis/__init__.py | 0 .../generated/apis/default_api_interface.py | 173 - .../generated/models/__init__.py | 0 .../generated/models/add_fields.py | 29 - .../generated/models/add_fields_all_of.py | 28 - .../models/added_field_definition.py | 27 - .../generated/models/api_key_authenticator.py | 30 - .../models/api_key_authenticator_all_of.py | 29 - .../models/basic_http_authenticator.py | 30 - .../models/basic_http_authenticator_all_of.py | 29 - .../generated/models/bearer_authenticator.py | 28 - .../models/bearer_authenticator_all_of.py | 27 - .../models/cartesian_product_stream_slicer.py | 27 - .../cartesian_product_stream_slicer_all_of.py | 25 - .../generated/models/check_stream.py | 24 - .../models/composite_error_handler.py | 26 - .../models/composite_error_handler_all_of.py | 25 - .../models/config_component_schema.py | 30 - .../generated/models/connector_manifest.py | 30 - .../models/constant_backoff_strategy.py | 28 - .../constant_backoff_strategy_all_of.py | 27 - .../models/cursor_pagination_strategy.py | 36 - .../cursor_pagination_strategy_all_of.py | 35 - .../models/datetime_stream_slicer.py | 53 - .../models/datetime_stream_slicer_all_of.py | 51 - .../declarative_oauth2_authenticator.py | 48 - ...declarative_oauth2_authenticator_all_of.py | 47 - .../generated/models/declarative_stream.py | 49 - .../generated/models/default_error_handler.py | 35 - .../models/default_error_handler_all_of.py | 34 - .../generated/models/default_paginator.py | 42 - .../models/default_paginator_all_of.py | 40 - .../generated/models/default_schema_loader.py | 25 - .../models/default_schema_loader_all_of.py | 24 - .../generated/models/dpath_extractor.py | 31 - .../models/dpath_extractor_all_of.py | 30 - .../models/exponential_backoff_strategy.py | 28 - .../exponential_backoff_strategy_all_of.py | 27 - .../generated/models/extra_models.py | 8 - .../generated/models/http_request.py | 32 - .../generated/models/http_requester.py | 45 - .../generated/models/http_requester_all_of.py | 43 - .../generated/models/http_response.py | 28 - .../generated/models/http_response_filter.py | 37 - .../generated/models/interpolated_boolean.py | 24 - .../interpolated_request_options_provider.py | 34 - ...polated_request_options_provider_all_of.py | 33 - .../generated/models/interpolated_string.py | 26 - .../models/invalid_input_exception_info.py | 31 - .../models/invalid_input_property.py | 28 - .../generated/models/json_decoder.py | 22 - .../models/json_file_schema_loader.py | 28 - .../models/json_file_schema_loader_all_of.py | 27 - .../generated/models/known_exception_info.py | 28 - .../generated/models/list_stream_slicer.py | 35 - .../models/list_stream_slicer_all_of.py | 33 - .../generated/models/min_max_datetime.py | 33 - .../generated/models/no_auth.py | 22 - .../generated/models/no_pagination.py | 23 - .../generated/models/offset_increment.py | 25 - .../models/offset_increment_all_of.py | 24 - .../generated/models/page_increment.py | 27 - .../generated/models/page_increment_all_of.py | 26 - .../generated/models/paginator.py | 22 - .../generated/models/parent_stream_config.py | 31 - .../models/parsed_add_field_definition.py | 27 - .../generated/models/record_filter.py | 26 - .../generated/models/record_selector.py | 29 - .../models/record_selector_all_of.py | 28 - .../generated/models/remove_fields.py | 25 - .../generated/models/remove_fields_all_of.py | 24 - .../generated/models/request_option.py | 26 - .../generated/models/requester.py | 22 - .../generated/models/resolve_manifest.py | 24 - .../models/resolve_manifest_request_body.py | 24 - .../generated/models/simple_retriever.py | 47 - .../models/simple_retriever_all_of.py | 46 - .../generated/models/single_slice.py | 23 - .../generated/models/stream_read.py | 31 - .../generated/models/stream_read_pages.py | 30 - .../models/stream_read_request_body.py | 42 - .../models/stream_read_slice_descriptor.py | 26 - .../generated/models/stream_read_slices.py | 30 - .../generated/models/stream_slicer.py | 22 - .../generated/models/streams_list_read.py | 25 - .../models/streams_list_read_streams.py | 26 - .../models/streams_list_request_body.py | 26 - .../generated/models/substream_slicer.py | 27 - .../models/substream_slicer_all_of.py | 25 - .../wait_time_from_header_backoff_strategy.py | 30 - ...ime_from_header_backoff_strategy_all_of.py | 29 - ...until_time_from_header_backoff_strategy.py | 33 - ...ime_from_header_backoff_strategy_all_of.py | 32 - .../connector_builder/impl/adapter.py | 42 - .../connector_builder/impl/default_api.py | 308 - .../impl/low_code_cdk_adapter.py | 75 - ...onnector_builder_server-0.40.21-py3.10.egg | Bin 3317 -> 0 bytes .../gradle.properties | 1 - .../test_integration_test.py | 7 - .../openapi/README.md | 25 - .../openapi/generator_config.yaml | 4 - .../openapi/templates/api_interfaces.mustache | 121 - airbyte-connector-builder-server/pytest.ini | 7 - .../run_format.sh | 26 - airbyte-connector-builder-server/run_tests.sh | 14 - airbyte-connector-builder-server/setup.py | 59 - .../src/main/openapi/openapi.yaml | 338 - .../impl/test_default_api.py | 920 - .../impl/test_low_code_cdk_adapter.py | 354 - .../unit_tests/test_unit_test.py | 7 - airbyte-container-orchestrator/Dockerfile | 28 - airbyte-container-orchestrator/build.gradle | 95 - .../gradle.properties | 1 - airbyte-container-orchestrator/readme.md | 6 - .../container_orchestrator/Application.java | 89 - .../AsyncStateManager.java | 101 - .../EventListeners.java | 90 - .../HeartbeatController.java | 34 - .../config/ConfigFactory.java | 92 - .../config/ContainerOrchestratorFactory.java | 126 - .../orchestrator/DbtJobOrchestrator.java | 93 - .../orchestrator/JobOrchestrator.java | 47 - .../orchestrator/NoOpOrchestrator.java | 36 - .../NormalizationJobOrchestrator.java | 88 - .../ReplicationJobOrchestrator.java | 206 - .../src/main/resources/application.yml | 53 - .../src/main/resources/micronaut-banner.txt | 8 - .../ApplicationTest.java | 58 - .../AsyncStateManagerTest.java | 111 - .../EventListenersTest.java | 49 - .../HeartbeatControllerTest.java | 33 - .../config/ConfigFactoryTest.java | 67 - .../ContainerOrchestratorFactoryK8sTest.java | 27 - .../ContainerOrchestratorFactoryTest.java | 136 - .../src/test/resources/application.yml | 23 - .../src/test/resources/files/KUBE_POD_INFO | 8 - .../src/test/resources/files/application.txt | 1 - .../files/destinationLauncherConfig.json | 8 - .../src/test/resources/files/envMap.json | 31 - .../src/test/resources/files/input.json | 162 - .../test/resources/files/jobRunConfig.json | 4 - airbyte-cron/Dockerfile | 15 - airbyte-cron/LICENSE | 21 - airbyte-cron/build.gradle | 52 - airbyte-cron/gradle.properties | 1 - .../airbyte/cron/ApplicationInitializer.java | 22 - .../io/airbyte/cron/MicronautCronRunner.java | 25 - .../cron/config/ApplicationBeanFactory.java | 40 - .../cron/config/DatabaseBeanFactory.java | 96 - .../cron/selfhealing/DefinitionsUpdater.java | 61 - .../io/airbyte/cron/selfhealing/Temporal.java | 33 - .../cron/selfhealing/WorkspaceCleaner.java | 83 - .../src/main/resources/application.yml | 127 - .../src/main/resources/micronaut-banner.txt | 8 - airbyte-metrics/reporter/Dockerfile | 15 - airbyte-metrics/reporter/README.md | 5 - airbyte-metrics/reporter/build.gradle | 42 - airbyte-metrics/reporter/gradle.properties | 1 - .../airbyte/metrics/reporter/Application.java | 23 - .../io/airbyte/metrics/reporter/Emitter.java | 223 - .../metrics/reporter/EventListeners.java | 56 - .../metrics/reporter/MetricRepository.java | 299 - .../metrics/reporter/ReporterFactory.java | 24 - .../src/main/resources/application.yml | 38 - .../src/main/resources/micronaut-banner.txt | 8 - .../airbyte/metrics/reporter/EmitterTest.java | 186 - .../reporter/MetricRepositoryTest.java | 680 - airbyte-proxy/401.html | 19 - airbyte-proxy/Dockerfile | 28 - airbyte-proxy/LICENSE | 21 - airbyte-proxy/README.md | 14 - airbyte-proxy/build.gradle | 21 - airbyte-proxy/gradle.properties | 1 - airbyte-proxy/nginx-auth.conf.template | 82 - airbyte-proxy/nginx-no-auth.conf.template | 55 - airbyte-proxy/run.sh | 23 - airbyte-proxy/test.sh | 129 - airbyte-server/.gitignore | 1 - airbyte-server/Dockerfile | 17 - airbyte-server/build.gradle | 130 - airbyte-server/gradle.properties | 1 - airbyte-server/readme.md | 5 - .../java/io/airbyte/server/Application.java | 15 - .../java/io/airbyte/server/CorsFilter.java | 29 - .../airbyte/server/DatabaseEventListener.java | 50 - .../java/io/airbyte/server/ServerApp.java | 384 - .../java/io/airbyte/server/ServerFactory.java | 105 - .../io/airbyte/server/ServerRunnable.java | 11 - .../io/airbyte/server/apis/ApiHelper.java | 39 - .../server/apis/AttemptApiController.java | 58 - .../server/apis/ConnectionApiController.java | 127 - .../server/apis/DestinationApiController.java | 118 - .../DestinationDefinitionApiController.java | 134 - ...nDefinitionSpecificationApiController.java | 38 - .../apis/DestinationOauthApiController.java | 64 - .../server/apis/HealthApiController.java | 35 - .../server/apis/JobsApiController.java | 100 - .../server/apis/LogsApiController.java | 40 - .../server/apis/NotFoundController.java | 36 - .../apis/NotificationsApiController.java | 56 - .../server/apis/OpenapiApiController.java | 37 - .../server/apis/OperationApiController.java | 94 - .../server/apis/SchedulerApiController.java | 57 - .../server/apis/SourceApiController.java | 144 - .../apis/SourceDefinitionApiController.java | 134 - ...eDefinitionSpecificationApiController.java | 38 - .../server/apis/SourceOauthApiController.java | 63 - .../server/apis/StateApiController.java | 49 - .../server/apis/WebBackendApiController.java | 113 - .../server/apis/WorkspaceApiController.java | 121 - .../server/config/ApplicationBeanFactory.java | 116 - .../config/CloudStorageBeanFactory.java | 92 - .../server/config/DatabaseBeanFactory.java | 125 - .../server/config/HelperBeanFactory.java | 21 - .../config/JobErrorReportingBeanFactory.java | 61 - .../config/SecretPersistenceBeanFactory.java | 135 - .../server/config/TemporalBeanFactory.java | 76 - .../errors/InvalidInputExceptionHandler.java | 33 - .../errors/InvalidJsonExceptionHandler.java | 31 - .../InvalidJsonInputExceptionHandler.java | 31 - .../server/errors/KnownExceptionHandler.java | 30 - .../errors/NotFoundExceptionHandler.java | 38 - .../errors/UncaughtExceptionHandler.java | 34 - .../src/main/resources/application.yml | 162 - .../src/main/resources/micronaut-banner.txt | 11 - .../server/apis/HealthCheckApiTest.java | 29 - airbyte-temporal/.gitignore | 2 - airbyte-temporal/Dockerfile | 8 - airbyte-temporal/README.md | 44 - airbyte-temporal/build.gradle | 10 - airbyte-temporal/gradle.properties | 1 - airbyte-temporal/scripts/build-temporal.sh | 8 - .../scripts/update-and-start-temporal.sh | 134 - airbyte-tests/build.gradle | 111 - airbyte-tests/readme.md | 5 - .../acceptance/AdvancedAcceptanceTests.java | 276 - .../test/acceptance/BasicAcceptanceTests.java | 1594 -- .../test/acceptance/CdcAcceptanceTests.java | 602 - .../ContainerOrchestratorAcceptanceTests.java | 224 - .../acceptance/VersioningAcceptanceTests.java | 128 - .../resources/postgres_init.sql | 33 - .../resources/postgres_init_cdc.sql | 79 - ...postgres_second_schema_multiple_tables.sql | 58 - .../postgres_separate_schema_same_table.sql | 36 - .../ImportApi.java | 118 - .../MigrationAcceptanceTest.java | 229 - .../03a4c904-c91d-447f-ab59-27a43b52c2fd.gz | Bin 5774 -> 0 bytes ...r-compose-migration-test-0-32-0-alpha.yaml | 203 - .../env-file-migration-test-0-32-0.env | 86 - airbyte-webapp-e2e-tests/.eslintrc.js | 52 - airbyte-webapp-e2e-tests/.gitignore | 33 - airbyte-webapp-e2e-tests/.npmrc | 1 - airbyte-webapp-e2e-tests/.nvmrc | 1 - airbyte-webapp-e2e-tests/.prettierrc.js | 1 - airbyte-webapp-e2e-tests/README.md | 38 - airbyte-webapp-e2e-tests/build.gradle | 28 - airbyte-webapp-e2e-tests/cypress.json | 19 - .../cypress/commands/api/api.ts | 67 - .../cypress/commands/api/index.ts | 2 - .../cypress/commands/api/payloads.ts | 66 - .../cypress/commands/api/types.ts | 77 - .../cypress/commands/api/workspace.ts | 9 - .../cypress/commands/common.ts | 51 - .../cypress/commands/connection.ts | 48 - .../cypress/commands/connector.ts | 54 - .../cypress/commands/connectorBuilder.ts | 69 - .../cypress/commands/db/db.ts | 51 - .../cypress/commands/db/index.ts | 1 - .../cypress/commands/db/queries.ts | 88 - .../cypress/commands/destination.ts | 58 - .../cypress/commands/interceptors.ts | 22 - .../cypress/commands/source.ts | 58 - .../cypress/commands/workspaces.ts | 14 - airbyte-webapp-e2e-tests/cypress/global.d.ts | 1 - .../integration/autoDetectSchema.spec.ts | 174 - .../cypress/integration/base.spec.ts | 30 - .../cypress/integration/connection.spec.ts | 581 - .../connection/streamTable.spec.ts | 175 - .../integration/connectorBuilder.spec.ts | 41 - .../cypress/integration/destination.spec.ts | 33 - .../cypress/integration/onboarding.spec.ts | 20 - .../cypress/integration/source.spec.ts | 97 - .../cypress/pages/connectionPage.ts | 12 - .../cypress/pages/connectorBuilderPage.ts | 96 - .../cypress/pages/connnectionsListPage.ts | 23 - .../cypress/pages/createConnectorPage.ts | 63 - .../cypress/pages/destinationPage.ts | 21 - .../cypress/pages/modals/catalogDiffModal.ts | 20 - .../cypress/pages/newConnectionPage.ts | 70 - .../cypress/pages/replicationPage.ts | 237 - .../cypress/pages/settingsConnectionPage.ts | 18 - .../cypress/pages/sidebar.ts | 10 - .../cypress/pages/sourcePage.ts | 28 - .../cypress/plugins/index.ts | 46 - .../cypress/support/index.js | 0 airbyte-webapp-e2e-tests/dummy_api.js | 28 - airbyte-webapp-e2e-tests/package-lock.json | 5732 ------ airbyte-webapp-e2e-tests/package.json | 29 - airbyte-webapp-e2e-tests/tsconfig.json | 30 - airbyte-webapp/.env | 6 - airbyte-webapp/.eslintrc.js | 129 - airbyte-webapp/.gitattributes | 1 - airbyte-webapp/.gitignore | 42 - airbyte-webapp/.husky/pre-commit | 10 - airbyte-webapp/.npmrc | 2 - airbyte-webapp/.nvmrc | 1 - airbyte-webapp/.prettierrc.js | 4 - airbyte-webapp/.storybook/logo.png | Bin 4866 -> 0 bytes airbyte-webapp/.storybook/main.ts | 12 - airbyte-webapp/.storybook/manager.ts | 7 - airbyte-webapp/.storybook/preview.ts | 8 - airbyte-webapp/.storybook/theme.tsx | 8 - airbyte-webapp/.storybook/withProvider.tsx | 58 - airbyte-webapp/.stylelintignore | 1 - airbyte-webapp/.stylelintrc | 24 - airbyte-webapp/Dockerfile | 7 - airbyte-webapp/README.md | 26 - airbyte-webapp/STYLEGUIDE.md | 72 - airbyte-webapp/babel.config.js | 12 - airbyte-webapp/build.gradle | 145 - .../docs/HowTo-ConnectionSpecification.md | 35 - airbyte-webapp/docs/HowTo-EnvVariables.md | 28 - airbyte-webapp/docs/img.png | Bin 173578 -> 0 bytes airbyte-webapp/gradle.properties | 1 - airbyte-webapp/index.html | 28 - airbyte-webapp/jest.config.ts | 22 - airbyte-webapp/nginx/default.conf.template | 55 - airbyte-webapp/orval.config.ts | 63 - airbyte-webapp/package.json | 215 - airbyte-webapp/packages/README.md | 2 - .../packages/eslint-plugin/index.js | 12 - .../no-hardcoded-connector-ids.js | 38 - .../packages/stylelint-plugin/index.js | 12 - .../no-color-variables-in-rgba.js | 37 - .../stylelint-plugin/no-use-renaming.js | 33 - .../packages/vite-plugins/build-info.ts | 26 - .../packages/vite-plugins/doc-middleware.ts | 27 - airbyte-webapp/packages/vite-plugins/index.ts | 2 - .../patches/react-virtualized@9.22.3.patch | 10 - airbyte-webapp/pnpm-lock.yaml | 16033 ---------------- airbyte-webapp/public/cactus.png | Bin 17018 -> 0 bytes airbyte-webapp/public/cloud-main-logo.svg | 5 - .../google/btn_google_light_normal_ios.svg | 43 - .../public/default-logo-catalog.svg | 3 - airbyte-webapp/public/empty-connections.png | Bin 250324 -> 0 bytes airbyte-webapp/public/empty-destinations.png | Bin 137076 -> 0 bytes airbyte-webapp/public/empty-sources.png | Bin 155544 -> 0 bytes airbyte-webapp/public/favicon.ico | Bin 11438 -> 0 bytes .../public/fonts/inter/Inter-italic.var.woff2 | Bin 245036 -> 0 bytes .../public/fonts/inter/Inter-roman.var.woff2 | Bin 227180 -> 0 bytes .../public/fonts/roboto/Roboto-Medium.eot | Bin 183972 -> 0 bytes .../public/fonts/roboto/Roboto-Medium.svg | 1063 - .../public/fonts/roboto/Roboto-Medium.ttf | Bin 183780 -> 0 bytes .../public/fonts/roboto/Roboto-Medium.woff | Bin 82980 -> 0 bytes .../public/fonts/roboto/Roboto-Medium.woff2 | Bin 50224 -> 0 bytes .../fonts/robotoMono/RobotoMono-Regular.eot | Bin 109454 -> 0 bytes .../fonts/robotoMono/RobotoMono-Regular.svg | 2811 --- .../fonts/robotoMono/RobotoMono-Regular.ttf | Bin 109760 -> 0 bytes .../fonts/robotoMono/RobotoMono-Regular.woff | Bin 63652 -> 0 bytes .../fonts/robotoMono/RobotoMono-Regular.woff2 | Bin 47924 -> 0 bytes airbyte-webapp/public/images/airbyte/logo.svg | 4 - .../images/connector-builder/import-yaml.svg | 155 - .../load-existing-connector.svg | 352 - .../connector-builder/start-from-scratch.svg | 223 - .../public/images/octavia/biting-nails.png | Bin 19048 -> 0 bytes .../public/images/octavia/pointing.svg | 52 - .../images/testimonials/cartdotcom-logo.svg | 44 - .../testimonials/cartdotcom-person-photo.png | Bin 268490 -> 0 bytes airbyte-webapp/public/index.css | 85 - airbyte-webapp/public/logo.png | Bin 70895 -> 0 bytes airbyte-webapp/public/logo112.png | Bin 14871 -> 0 bytes airbyte-webapp/public/logo224.png | Bin 48413 -> 0 bytes airbyte-webapp/public/logo336.png | Bin 91734 -> 0 bytes airbyte-webapp/public/manifest.json | 30 - airbyte-webapp/public/newsletter.png | Bin 18353 -> 0 bytes airbyte-webapp/public/play.svg | 3 - airbyte-webapp/public/process-arrow.svg | 3 - airbyte-webapp/public/rectangle.svg | 3 - airbyte-webapp/public/robots.txt | 2 - airbyte-webapp/public/rocket.png | Bin 46928 -> 0 bytes airbyte-webapp/public/videoCover.png | Bin 109073 -> 0 bytes airbyte-webapp/public/welcome.svg | 52 - airbyte-webapp/scripts/dev-overwrites.js | 22 - airbyte-webapp/scripts/environment.js | 25 - airbyte-webapp/scripts/license-check.js | 111 - .../scripts/load-declarative-schema.sh | 28 - airbyte-webapp/scripts/validate-links.ts | 39 - airbyte-webapp/src/App.tsx | 80 - .../ArrayOfObjectsEditor.module.scss | 11 - .../ArrayOfObjectsEditor.tsx | 96 - .../components/EditorHeader.module.scss | 13 - .../components/EditorHeader.test.tsx | 46 - .../components/EditorHeader.tsx | 39 - .../components/EditorRow.module.scss | 30 - .../components/EditorRow.tsx | 60 - .../components/ArrayOfObjectsEditor/index.tsx | 4 - .../CloudInviteUsersHint.tsx | 15 - .../components/CloudInviteUsersHint/index.ts | 1 - .../FormPageContent.module.scss | 15 - .../ConnectorBlocks/FormPageContent.tsx | 27 - .../components/ConnectorBlocks/ItemTabs.tsx | 31 - .../TableItemTitle.module.scss | 36 - .../ConnectorBlocks/TableItemTitle.tsx | 77 - .../src/components/ConnectorBlocks/index.tsx | 5 - .../ConnectorCard/ConnectorCard.module.scss | 55 - .../ConnectorCard/ConnectorCard.tsx | 36 - .../src/components/ConnectorCard/index.tsx | 1 - .../EntityTable/ConnectionTable.module.scss | 11 - .../EntityTable/ConnectionTable.tsx | 199 - .../ImplementationTable.module.scss | 9 - .../EntityTable/ImplementationTable.tsx | 142 - .../components/AllConnectionsStatusCell.tsx | 52 - .../components/ChangesStatusIcon.module.scss | 21 - .../components/ChangesStatusIcon.tsx | 42 - .../components/ConnectEntitiesCell.tsx | 65 - .../components/ConnectionSettingsCell.tsx | 51 - .../ConnectionStatusCell.module.scss | 11 - .../components/ConnectionStatusCell.tsx | 61 - .../components/ConnectorNameCell.module.scss | 13 - .../components/ConnectorNameCell.tsx | 21 - .../components/EntityNameCell.module.scss | 14 - .../EntityTable/components/EntityNameCell.tsx | 20 - .../components/FrequencyCell.module.scss | 10 - .../EntityTable/components/FrequencyCell.tsx | 34 - .../components/LastSyncCell.module.scss | 10 - .../EntityTable/components/LastSyncCell.tsx | 24 - .../components/StatusCell.module.scss | 7 - .../components/StatusCell.test.tsx | 82 - .../EntityTable/components/StatusCell.tsx | 44 - .../components/StatusCellControl.module.scss | 7 - .../components/StatusCellControl.tsx | 85 - .../src/components/EntityTable/index.tsx | 4 - .../src/components/EntityTable/types.ts | 56 - .../src/components/EntityTable/utils.tsx | 130 - .../GroupControls/GroupControls.module.scss | 63 - .../GroupControls/GroupControls.tsx | 36 - .../GroupControls/index.stories.tsx | 94 - .../src/components/GroupControls/index.tsx | 3 - .../Indicator/Indicator.module.scss | 12 - .../src/components/Indicator/Indicator.tsx | 15 - .../src/components/Indicator/index.tsx | 4 - .../components/JobItem/JobItem.module.scss | 10 - .../src/components/JobItem/JobItem.tsx | 77 - .../components/JobItem/attemptLinkUtils.ts | 36 - .../components/AttemptDetails.module.scss | 28 - .../JobItem/components/AttemptDetails.tsx | 95 - .../components/ContentWrapper.module.scss | 3 - .../JobItem/components/ContentWrapper.tsx | 36 - .../DebugInfoDetailsModal.module.scss | 3 - .../JobItem/components/DownloadButton.tsx | 40 - .../JobItem/components/ErrorDetails.tsx | 60 - .../JobItem/components/JobLogs.module.scss | 5 - .../components/JobItem/components/JobLogs.tsx | 120 - .../components/LinkToAttemptButton.tsx | 51 - .../components/JobItem/components/Logs.tsx | 60 - .../JobItem/components/LogsDetails.tsx | 49 - .../JobItem/components/MainInfo.module.scss | 83 - .../JobItem/components/MainInfo.tsx | 125 - .../components/ResetStreamDetails.module.scss | 27 - .../JobItem/components/ResetStreamDetails.tsx | 21 - .../components/JobItem/components/Tabs.tsx | 33 - .../src/components/JobItem/index.ts | 1 - .../src/components/JobItem/types.ts | 5 - .../src/components/JobItem/utils.ts | 28 - airbyte-webapp/src/components/Label/Label.tsx | 54 - airbyte-webapp/src/components/Label/index.tsx | 4 - .../LabeledControl/ControlLabels.module.scss | 17 - .../LabeledControl/ControlLabels.tsx | 48 - .../src/components/LabeledControl/index.tsx | 1 - .../components/LabeledInput/LabeledInput.tsx | 15 - .../src/components/LabeledInput/index.tsx | 4 - .../LabeledRadioButton/LabeledRadioButton.tsx | 49 - .../components/LabeledRadioButton/index.tsx | 4 - .../LabeledSwitch/LabeledSwitch.module.scss | 33 - .../LabeledSwitch/LabeledSwitch.tsx | 35 - .../src/components/LabeledSwitch/index.tsx | 1 - .../components/LoadingPage/LoadingPage.tsx | 25 - .../src/components/LoadingPage/index.tsx | 4 - .../LoadingSchema/LoadingSchema.tsx | 32 - .../src/components/LoadingSchema/index.tsx | 3 - .../components/Placeholder/Placeholder.tsx | 22 - .../src/components/Placeholder/index.tsx | 5 - .../src/components/Placeholder/types.ts | 5 - .../ReleaseStageBadge.module.scss | 19 - .../ReleaseStageBadge/ReleaseStageBadge.tsx | 50 - .../ReleaseStageBadge/index.stories.tsx | 16 - .../src/components/ReleaseStageBadge/index.ts | 1 - .../SimpleTableComponents.tsx | 39 - .../SimpleTableComponents/index.tsx | 3 - .../src/components/base/Titles/Titles.tsx | 26 - .../src/components/base/Titles/index.tsx | 1 - .../ApiErrorBoundary/ApiErrorBoundary.tsx | 159 - .../ServerUnavailableView.tsx | 27 - .../common/ApiErrorBoundary/index.ts | 1 - .../ConfirmationModal.module.scss | 17 - .../ConfirmationModal/ConfirmationModal.tsx | 58 - .../common/ConfirmationModal/index.ts | 1 - .../ConnectorIcon/ConnectorIcon.module.scss | 5 - .../ConnectorIcon.story.module.scss | 25 - .../common/ConnectorIcon/ConnectorIcon.tsx | 17 - .../common/ConnectorIcon/index.stories.tsx | 46 - .../components/common/ConnectorIcon/index.ts | 1 - .../DataGeographyDropdown.module.scss | 18 - .../DataGeographyDropdown.tsx | 59 - .../common/DataGeographyDropdown/index.ts | 1 - .../DefaultLogoCatalog/DefaultLogoCatalog.tsx | 8 - .../common/DefaultLogoCatalog/index.ts | 1 - .../DeleteBlock/DeleteBlock.module.scss | 17 - .../common/DeleteBlock/DeleteBlock.tsx | 34 - .../components/common/DeleteBlock/index.ts | 1 - .../EmptyResourceBlock.module.scss | 27 - .../EmptyResourceBlock/EmptyResourceBlock.tsx | 18 - .../common/EmptyResourceBlock/index.ts | 1 - .../FormChangeTracker/FormChangeTracker.tsx | 32 - .../common/FormChangeTracker/index.ts | 1 - .../components/common/HeadTitle/HeadTitle.tsx | 44 - .../src/components/common/HeadTitle/index.ts | 1 - .../src/components/common/Link/Link.tsx | 23 - .../src/components/common/Link/index.ts | 1 - .../MainPageWithScroll.module.scss | 27 - .../MainPageWithScroll/MainPageWithScroll.tsx | 30 - .../common/MainPageWithScroll/index.ts | 1 - .../BaseClearView.module.scss | 22 - .../PageViewContainer/BaseClearView.tsx | 21 - .../common/PageViewContainer/PaddedCard.tsx | 10 - .../PageViewContainer/PageViewContainer.tsx | 12 - .../common/PageViewContainer/index.ts | 1 - .../src/components/common/Version/Version.tsx | 28 - .../src/components/common/Version/index.ts | 1 - .../CatalogDiffModal.module.scss | 6 - .../CatalogDiffModal.test.tsx | 275 - .../CatalogDiffModal/CatalogDiffModal.tsx | 49 - .../DiffAccordion.module.scss | 27 - .../CatalogDiffModal/DiffAccordion.tsx | 51 - .../DiffAccordionHeader.module.scss | 11 - .../CatalogDiffModal/DiffAccordionHeader.tsx | 47 - .../DiffFieldTable.module.scss | 30 - .../CatalogDiffModal/DiffFieldTable.tsx | 37 - .../CatalogDiffModal/DiffHeader.tsx | 27 - .../DiffIconBlock.module.scss | 8 - .../CatalogDiffModal/DiffIconBlock.tsx | 64 - .../CatalogDiffModal/DiffSection.module.scss | 40 - .../CatalogDiffModal/DiffSection.tsx | 61 - .../CatalogDiffModal/FieldRow.module.scss | 70 - .../connection/CatalogDiffModal/FieldRow.tsx | 67 - .../CatalogDiffModal/FieldSection.module.scss | 39 - .../CatalogDiffModal/FieldSection.tsx | 54 - .../CatalogDiffModal/StreamRow.module.scss | 72 - .../connection/CatalogDiffModal/StreamRow.tsx | 57 - .../CatalogDiffModal/index.stories.tsx | 134 - .../connection/CatalogDiffModal/index.ts | 1 - .../connection/CatalogDiffModal/types.ts | 9 - .../connection/CatalogDiffModal/utils.tsx | 21 - .../connection/CatalogTree/Arrow.module.scss | 19 - .../connection/CatalogTree/Arrow.tsx | 29 - .../CatalogTree/BulkHeader.module.scss | 17 - .../connection/CatalogTree/BulkHeader.tsx | 134 - .../CatalogTree/CatalogSection.module.scss | 15 - .../connection/CatalogTree/CatalogSection.tsx | 246 - .../CatalogTree/CatalogTree.module.scss | 12 - .../connection/CatalogTree/CatalogTree.tsx | 95 - .../CatalogTree/CatalogTreeBody.module.scss | 8 - .../CatalogTree/CatalogTreeBody.tsx | 79 - .../CatalogTree/CatalogTreeHeader.module.scss | 30 - .../CatalogTree/CatalogTreeHeader.tsx | 76 - .../CatalogTree/CatalogTreeSearch.module.scss | 15 - .../CatalogTree/CatalogTreeSearch.tsx | 30 - .../CatalogTreeSubheader.module.scss | 18 - .../CatalogTree/CatalogTreeSubheader.tsx | 53 - .../connection/CatalogTree/DataTypeCell.tsx | 9 - .../connection/CatalogTree/FieldHeader.tsx | 44 - .../connection/CatalogTree/FieldRow.tsx | 127 - .../CatalogTree/PathPopout.module.scss | 5 - .../connection/CatalogTree/PathPopout.tsx | 99 - .../CatalogTree/PathPopoutButton.module.scss | 32 - .../CatalogTree/PathPopoutButton.tsx | 41 - .../CatalogTree/StreamFieldTable.module.scss | 15 - .../CatalogTree/StreamFieldTable.tsx | 74 - .../CatalogTree/StreamHeader.module.scss | 68 - .../connection/CatalogTree/StreamHeader.tsx | 181 - .../CatalogTree/SyncSettingsDropdown.tsx | 119 - .../CatalogTree/TreeRowWrapper.module.scss | 20 - .../connection/CatalogTree/TreeRowWrapper.tsx | 23 - .../connection/CatalogTree/index.tsx | 1 - .../next/BulkEditPanel.module.scss | 77 - .../CatalogTree/next/BulkEditPanel.test.tsx | 222 - .../CatalogTree/next/BulkEditPanel.tsx | 184 - .../next/CatalogTreeTableCell.module.scss | 39 - .../CatalogTree/next/CatalogTreeTableCell.tsx | 93 - .../next/CatalogTreeTableHeader.module.scss | 23 - .../next/CatalogTreeTableHeader.tsx | 172 - .../next/CatalogTreeTableRow.module.scss | 56 - .../CatalogTree/next/CatalogTreeTableRow.tsx | 139 - .../next/CatalogTreeTableRowIcon.module.scss | 30 - .../next/CatalogTreeTableRowIcon.tsx | 58 - .../next/StreamConnectionHeader.module.scss | 48 - .../next/StreamConnectionHeader.tsx | 38 - .../StreamDetailsPanel.module.scss | 27 - .../StreamDetailsPanel/StreamDetailsPanel.tsx | 65 - .../ConnectorHeaderGroupIcon.module.scss | 13 - .../ConnectorHeaderGroupIcon.tsx | 20 - .../CursorCell/CursorCell.module.scss | 8 - .../CursorCell/CursorCell.tsx | 49 - .../StreamFieldsTable/CursorCell/index.tsx | 1 - .../StreamFieldsTable/PKCell/PKCell.tsx | 37 - .../StreamFieldsTable/PKCell/index.tsx | 1 - .../StreamFieldsTable.module.scss | 114 - .../StreamFieldsTable.test.tsx | 126 - .../StreamFieldsTable/StreamFieldsTable.tsx | 297 - .../SyncFieldCell/SyncFieldCell.tsx | 77 - .../StreamFieldsTable/SyncFieldCell/index.ts | 1 - .../StreamPanelHeader.module.scss | 42 - .../StreamPanelHeader/StreamPanelHeader.tsx | 67 - .../next/StreamPathSelect.module.scss | 7 - .../CatalogTree/next/StreamPathSelect.tsx | 89 - .../next/SyncModeSelect.module.scss | 6 - .../CatalogTree/next/SyncModeSelect.tsx | 55 - .../__snapshots__/BulkEditPanel.test.tsx.snap | 266 - .../next/useCatalogTreeTableRowProps.test.tsx | 147 - .../next/useCatalogTreeTableRowProps.tsx | 73 - .../CatalogTree/streamConfigHelpers/index.ts | 1 - .../streamConfigHelpers.test.ts | 458 - .../streamConfigHelpers.ts | 184 - .../connection/CatalogTree/styles.tsx | 32 - .../connection/CatalogTree/utils.ts | 16 - .../ConnectionBlock.module.scss | 20 - .../ConnectionBlock/ConnectionBlock.tsx | 22 - .../ConnectionBlock/ConnectionBlockItem.tsx | 40 - .../connection/ConnectionBlock/index.ts | 1 - .../ConnectionEditFormCard.module.scss | 12 - .../ConnectionEditFormCard.tsx | 68 - .../ConnectionEditFormCard/index.ts | 1 - .../ConnectionForm/ConnectionForm.module.scss | 22 - .../ConnectionFormFields.module.scss | 37 - .../ConnectionForm/ConnectionFormFields.tsx | 152 - .../ConnectionForm/CreateControls.module.scss | 5 - .../ConnectionForm/CreateControls.tsx | 69 - .../ConnectionForm/EditControls.module.scss | 5 - .../ConnectionForm/EditControls.tsx | 53 - .../NamespaceDefinitionField.module.scss | 1 - .../NamespaceDefinitionField.tsx | 55 - ...BreakingChangesPreferenceField.module.scss | 17 - .../NonBreakingChangesPreferenceField.tsx | 55 - .../NormalizationField.module.scss | 5 - .../ConnectionForm/NormalizationField.tsx | 52 - .../ConnectionForm/OctaviaRedFlag.tsx | 59 - .../ConnectionForm/OctaviaYellowFlag.tsx | 61 - .../ConnectionForm/OperationsSection.tsx | 65 - .../ResponseMessage.module.scss | 16 - .../ConnectionForm/ResponseMessage.tsx | 33 - .../ConnectionForm/ScheduleField.module.scss | 29 - .../ConnectionForm/ScheduleField.tsx | 221 - .../SchemaChangeBackdrop.module.scss | 44 - .../ConnectionForm/SchemaChangeBackdrop.tsx | 42 - .../SchemaChangesBackdrop.test.tsx | 90 - .../ConnectionForm/Section.module.scss | 18 - .../connection/ConnectionForm/Section.tsx | 27 - .../SyncCatalogField.module.scss | 13 - .../ConnectionForm/SyncCatalogField.tsx | 67 - .../ConnectionForm/TransformationField.tsx | 76 - .../SchemaChangesBackdrop.test.tsx.snap | 99 - .../__snapshots__/formConfig.test.ts.snap | 1602 -- .../calculateInitialCatalog.test.ts | 982 - .../ConnectionForm/calculateInitialCatalog.ts | 216 - .../ConnectionForm/formConfig.test.ts | 204 - .../connection/ConnectionForm/formConfig.tsx | 478 - ...reshSourceSchemaWithConfirmationOnDirty.ts | 33 - .../ConnectionInfoCard.module.scss | 56 - .../ConnectionInfoCard.test.tsx | 102 - .../ConnectionInfoCard/ConnectionInfoCard.tsx | 79 - .../EnabledControl.module.scss | 22 - .../ConnectionInfoCard/EnabledControl.tsx | 72 - .../SchemaChangesDetected.module.scss | 21 - .../SchemaChangesDetected.test.tsx | 98 - .../SchemaChangesDetected.tsx | 61 - .../connection/ConnectionInfoCard/index.ts | 1 - .../ConnectionName/ConnectionName.module.scss | 82 - .../ConnectionName/ConnectionName.tsx | 97 - .../connection/ConnectionName/index.ts | 1 - .../AirbyteIllustration.module.scss | 9 - .../AirbyteIllustration.tsx | 173 - .../ConnectionOnboarding.module.scss | 103 - .../ConnectionOnboarding.tsx | 261 - .../connection/ConnectionOnboarding/index.ts | 1 - .../ConnectionOnboarding/plusIcon.svg | 3 - .../CreateConnectionForm.module.scss | 12 - .../CreateConnectionForm.test.tsx | 158 - .../CreateConnectionForm.tsx | 161 - .../CreateConnectionNameField.module.scss | 1 - .../CreateConnectionNameField.tsx | 44 - .../DataResidency.module.scss | 12 - .../CreateConnectionForm/DataResidency.tsx | 67 - .../CreateConnectionForm/SchemaError.tsx | 19 - .../TryAfterErrorBlock.module.scss | 14 - .../TryAfterErrorBlock.tsx | 32 - .../CreateConnectionForm.test.tsx.snap | 1226 -- .../connection/CreateConnectionForm/index.tsx | 1 - .../DestinationNamespaceModal.module.scss | 54 - .../DestinationNamespaceModal.tsx | 166 - .../ExampleSettingsTable.module.scss | 52 - .../ExampleSettingsTable.tsx | 43 - .../useExampleSettingsTable.ts | 160 - .../DestinationStreamNamesModal.module.scss | 29 - .../DestinationStreamNamesModal.tsx | 140 - .../JobProgress/JobProgress.module.scss | 23 - .../connection/JobProgress/JobProgress.tsx | 126 - .../JobProgress/JobProgressLine.module.scss | 24 - .../JobProgress/JobProgressLine.tsx | 29 - .../JobProgress/StreamProgress.module.scss | 73 - .../connection/JobProgress/StreamProgress.tsx | 96 - .../connection/JobProgress/index.tsx | 1 - .../connection/JobProgress/utils.test.ts | 59 - .../connection/JobProgress/utils.ts | 52 - .../TransformationForm.module.scss | 22 - .../TransformationForm/TransformationForm.tsx | 164 - .../connection/TransformationForm/index.tsx | 3 - .../TransformationForm/utils.test.ts | 86 - .../connection/TransformationForm/utils.ts | 16 - .../UpdateConnectionDataResidency.module.scss | 25 - .../UpdateConnectionDataResidency.tsx | 80 - .../UpdateConnectionDataResidency/index.ts | 1 - .../Builder/AddStreamButton.module.scss | 20 - .../Builder/AddStreamButton.tsx | 143 - .../Builder/AuthenticationSection.tsx | 237 - .../Builder/Builder.module.scss | 25 - .../connectorBuilder/Builder/Builder.tsx | 53 - .../Builder/BuilderCard.module.scss | 45 - .../connectorBuilder/Builder/BuilderCard.tsx | 196 - .../Builder/BuilderConfigView.module.scss | 16 - .../Builder/BuilderConfigView.tsx | 26 - .../Builder/BuilderField.module.scss | 7 - .../connectorBuilder/Builder/BuilderField.tsx | 163 - .../BuilderFieldWithInputs.module.scss | 63 - .../Builder/BuilderFieldWithInputs.tsx | 118 - .../Builder/BuilderList.module.scss | 13 - .../connectorBuilder/Builder/BuilderList.tsx | 55 - .../connectorBuilder/Builder/BuilderOneOf.tsx | 77 - .../Builder/BuilderOptional.module.scss | 34 - .../Builder/BuilderOptional.tsx | 26 - .../Builder/BuilderSidebar.module.scss | 118 - .../Builder/BuilderSidebar.tsx | 192 - .../Builder/BuilderTitle.module.scss | 51 - .../connectorBuilder/Builder/BuilderTitle.tsx | 44 - .../Builder/GlobalConfigView.module.scss | 5 - .../Builder/GlobalConfigView.tsx | 44 - .../Builder/InjectRequestOptionFields.tsx | 50 - .../Builder/InputsForm.module.scss | 16 - .../connectorBuilder/Builder/InputsForm.tsx | 297 - .../Builder/InputsView.module.scss | 40 - .../connectorBuilder/Builder/InputsView.tsx | 108 - .../Builder/KeyValueListField.module.scss | 27 - .../Builder/KeyValueListField.tsx | 113 - .../Builder/PaginationSection.tsx | 199 - .../Builder/RemoveButton.module.scss | 20 - .../connectorBuilder/Builder/RemoveButton.tsx | 12 - .../Builder/StreamConfigView.module.scss | 77 - .../Builder/StreamConfigView.tsx | 262 - .../Builder/StreamReferenceField.tsx | 58 - .../Builder/StreamSlicerSection.tsx | 275 - .../Builder/ToggleGroupField.module.scss | 12 - .../Builder/ToggleGroupField.tsx | 40 - .../Builder/UiYamlToggleButton.module.scss | 38 - .../Builder/UiYamlToggleButton.tsx | 54 - .../Builder/UserInputField.module.scss | 12 - .../Builder/UserInputField.tsx | 18 - .../BuilderPrompt.module.scss | 10 - .../connectorBuilder/BuilderPrompt.tsx | 60 - .../DownloadYamlButton.module.scss | 3 - .../connectorBuilder/DownloadYamlButton.tsx | 92 - .../SchemaConflictIndicator.module.scss | 5 - .../SchemaConflictIndicator.tsx | 13 - .../StreamTestingPanel/ConfigMenu.module.scss | 41 - .../StreamTestingPanel/ConfigMenu.tsx | 153 - .../ConfigMenuErrorBoundary.module.scss | 9 - .../ConfigMenuErrorBoundary.tsx | 66 - .../LogsDisplay.module.scss | 31 - .../StreamTestingPanel/LogsDisplay.tsx | 34 - .../PageDisplay.module.scss | 45 - .../StreamTestingPanel/PageDisplay.tsx | 123 - .../ResultDisplay.module.scss | 41 - .../StreamTestingPanel/ResultDisplay.tsx | 45 - .../SchemaDiffView.module.scss | 24 - .../StreamTestingPanel/SchemaDiffView.tsx | 192 - .../SliceSelector.module.scss | 16 - .../StreamTestingPanel/SliceSelector.tsx | 72 - .../StreamSelector.module.scss | 25 - .../StreamTestingPanel/StreamSelector.tsx | 87 - .../StreamTestButton.module.scss | 14 - .../StreamTestingPanel/StreamTestButton.tsx | 92 - .../StreamTester.module.scss | 41 - .../StreamTestingPanel/StreamTester.tsx | 198 - .../StreamTestingPanel.module.scss | 51 - .../StreamTestingPanel/StreamTestingPanel.tsx | 82 - .../StreamTestingPanel/index.tsx | 1 - .../YamlEditor/YamlEditor.module.scss | 22 - .../YamlEditor/YamlEditor.tsx | 143 - .../connectorBuilder/YamlEditor/index.tsx | 1 - .../connectorBuilder/builder-prompt-icon.svg | 57 - .../src/components/connectorBuilder/types.ts | 662 - .../connectorBuilder/useBuilderErrors.ts | 104 - .../useManifestToBuilderForm.test.ts | 459 - .../useManifestToBuilderForm.ts | 431 - .../src/components/connectorBuilder/utils.ts | 27 - .../DestinationConnectionTable.module.scss | 5 - .../DestinationConnectionTable.tsx | 30 - .../DestinationConnectionTable/index.ts | 1 - .../DestinationForm/DestinationForm.tsx | 91 - .../destination/DestinationForm/index.ts | 1 - .../DestinationsTable/DestinationsTable.tsx | 24 - .../destination/DestinationsTable/index.ts | 1 - .../src/components/icons/ArrowRightIcon.tsx | 8 - .../src/components/icons/CreditsIcon.tsx | 20 - .../src/components/icons/CrossIcon.tsx | 14 - .../src/components/icons/DocsIcon.tsx | 8 - .../src/components/icons/GAIcon.tsx | 20 - .../src/components/icons/InfoIcon.tsx | 8 - .../src/components/icons/MinusIcon.tsx | 9 - .../src/components/icons/ModificationIcon.tsx | 24 - .../src/components/icons/MoonIcon.tsx | 15 - .../src/components/icons/PauseIcon.tsx | 12 - .../src/components/icons/PencilIcon.tsx | 12 - .../src/components/icons/PlayIcon.tsx | 12 - .../src/components/icons/PlusIcon.tsx | 12 - .../src/components/icons/RotateIcon.tsx | 17 - airbyte-webapp/src/components/index.tsx | 11 - .../ui/Banner/AlertBanner.module.scss | 26 - .../src/components/ui/Banner/AlertBanner.tsx | 18 - .../components/ui/Banner/index.stories.tsx | 16 - .../src/components/ui/BarChart/BarChart.tsx | 87 - .../components/ui/BarChart/index.stories.tsx | 26 - .../src/components/ui/BarChart/index.tsx | 1 - .../ui/Breadcrumbs/Breadcrumbs.module.scss | 18 - .../components/ui/Breadcrumbs/Breadcrumbs.tsx | 35 - .../ui/Breadcrumbs/index.stories.tsx | 30 - .../src/components/ui/Breadcrumbs/index.tsx | 1 - .../components/ui/Button/Button.module.scss | 247 - .../src/components/ui/Button/Button.tsx | 77 - .../components/ui/Button/index.stories.tsx | 93 - .../src/components/ui/Button/index.tsx | 2 - .../src/components/ui/Button/types.tsx | 14 - .../components/ui/Callout/Callout.module.scss | 26 - .../src/components/ui/Callout/Callout.tsx | 23 - .../components/ui/Callout/index.stories.tsx | 25 - .../src/components/ui/Callout/index.ts | 1 - .../src/components/ui/Card/Card.module.scss | 46 - .../src/components/ui/Card/Card.tsx | 58 - .../src/components/ui/Card/index.stories.tsx | 15 - .../src/components/ui/Card/index.tsx | 3 - .../ui/CheckBox/CheckBox.module.scss | 47 - .../src/components/ui/CheckBox/CheckBox.tsx | 40 - .../components/ui/CheckBox/index.stories.tsx | 71 - .../src/components/ui/CheckBox/index.ts | 1 - .../ui/CodeEditor/CodeEditor.module.scss | 17 - .../components/ui/CodeEditor/CodeEditor.tsx | 106 - .../ui/CodeEditor/index.stories.tsx | 23 - .../src/components/ui/CodeEditor/index.tsx | 1 - .../ui/CollapsibleCard/CollapsibleCard.tsx | 50 - .../ui/CollapsibleCard/index.stories.tsx | 18 - .../components/ui/CollapsibleCard/index.ts | 1 - .../ui/DatePicker/DatePicker.module.scss | 146 - .../ui/DatePicker/DatePicker.test.tsx | 147 - .../components/ui/DatePicker/DatePicker.tsx | 166 - .../ui/DatePicker/index.stories.tsx | 40 - .../src/components/ui/DatePicker/index.ts | 1 - .../components/ui/DropDown/CustomSelect.tsx | 48 - .../src/components/ui/DropDown/DropDown.tsx | 89 - .../ui/DropDown/SelectContainer.tsx | 19 - .../ui/DropDown/components/DropDownText.tsx | 35 - .../DropDown/components/DropdownIndicator.tsx | 15 - .../ui/DropDown/components/Menu.tsx | 28 - .../ui/DropDown/components/Option.tsx | 88 - .../ui/DropDown/components/SingleValue.tsx | 35 - .../components/ui/DropDown/index.stories.tsx | 33 - .../src/components/ui/DropDown/index.tsx | 4 - .../ui/DropdownMenu/DropdownMenu.module.scss | 72 - .../ui/DropdownMenu/DropdownMenu.tsx | 94 - .../src/components/ui/DropdownMenu/index.tsx | 2 - .../src/components/ui/DropdownMenu/types.ts | 39 - .../src/components/ui/Flex/Flex.stories.tsx | 39 - .../ui/Flex/FlexContainer.module.scss | 89 - .../src/components/ui/Flex/FlexContainer.tsx | 80 - .../components/ui/Flex/FlexItem.module.scss | 25 - .../src/components/ui/Flex/FlexItem.tsx | 47 - .../src/components/ui/Flex/index.ts | 2 - .../components/ui/Heading/Heading.stories.tsx | 17 - .../src/components/ui/Heading/Heading.tsx | 50 - .../components/ui/Heading/heading.module.scss | 39 - .../src/components/ui/Heading/index.ts | 1 - .../ui/ImageBlock/ImageBlock.module.scss | 19 - .../ui/ImageBlock/ImageBlock.stories.tsx | 17 - .../components/ui/ImageBlock/ImageBlock.tsx | 24 - .../src/components/ui/ImageBlock/index.tsx | 1 - .../ui/InfoText/InfoText.module.scss | 50 - .../src/components/ui/InfoText/InfoText.tsx | 31 - .../src/components/ui/InfoText/constants.ts | 11 - .../components/ui/InfoText/index.stories.tsx | 20 - .../src/components/ui/InfoText/index.ts | 2 - .../src/components/ui/Input/Input.module.scss | 77 - .../src/components/ui/Input/Input.test.tsx | 155 - .../src/components/ui/Input/Input.tsx | 126 - .../src/components/ui/Input/index.stories.tsx | 19 - .../src/components/ui/Input/index.tsx | 1 - .../components/ui/ListBox/CaretDownIcon.svg | 6 - .../components/ui/ListBox/ListBox.module.scss | 78 - .../src/components/ui/ListBox/ListBox.tsx | 82 - .../components/ui/ListBox/index.stories.tsx | 36 - .../src/components/ui/ListBox/index.tsx | 1 - .../LoadingBackdrop.module.scss | 31 - .../LoadingBackdrop/LoadingBackdrop.test.tsx | 17 - .../ui/LoadingBackdrop/LoadingBackdrop.tsx | 29 - .../ui/LoadingBackdrop/index.stories.tsx | 26 - .../components/ui/LoadingBackdrop/index.tsx | 1 - .../ui/Markdown/Markdown.module.scss | 90 - .../src/components/ui/Markdown/Markdown.tsx | 32 - .../ui/Markdown/admonitions.module.scss | 51 - .../components/ui/Markdown/index.stories.tsx | 94 - .../src/components/ui/Markdown/index.ts | 1 - .../ui/Markdown/remarkAdmonitionsPlugin.ts | 25 - .../src/components/ui/Modal/Modal.module.scss | 54 - .../src/components/ui/Modal/Modal.tsx | 62 - .../components/ui/Modal/ModalBody.module.scss | 11 - .../src/components/ui/Modal/ModalBody.tsx | 29 - .../ui/Modal/ModalFooter.module.scss | 11 - .../src/components/ui/Modal/ModalFooter.tsx | 5 - .../src/components/ui/Modal/index.stories.tsx | 48 - .../src/components/ui/Modal/index.ts | 3 - .../components/ui/Multiselect/Multiselect.tsx | 131 - .../src/components/ui/Multiselect/index.tsx | 1 - .../ui/NextTable/NextTable.module.scss | 102 - .../ui/NextTable/NextTable.test.tsx | 41 - .../src/components/ui/NextTable/NextTable.tsx | 86 - .../components/ui/NextTable/index.stories.tsx | 47 - .../src/components/ui/NextTable/index.ts | 1 - .../src/components/ui/NextTable/types.ts | 5 - .../ui/NumberBadge/NumberBadge.module.scss | 40 - .../ui/NumberBadge/NumberBadge.stories.tsx | 16 - .../components/ui/NumberBadge/NumberBadge.tsx | 26 - .../src/components/ui/NumberBadge/index.tsx | 1 - .../components/ui/Overlay/Overlay.module.scss | 13 - .../src/components/ui/Overlay/Overlay.tsx | 20 - .../components/ui/Overlay/index.stories.tsx | 14 - .../src/components/ui/Overlay/index.ts | 1 - .../ui/PageHeader/PageHeader.module.scss | 43 - .../components/ui/PageHeader/PageHeader.tsx | 46 - .../ui/PageHeader/index.stories.tsx | 28 - .../src/components/ui/PageHeader/index.tsx | 1 - .../ui/Paginator/Paginator.module.scss | 56 - .../src/components/ui/Paginator/Paginator.tsx | 44 - .../src/components/ui/Paginator/index.tsx | 1 - .../ui/PillSelect/PillButton.module.scss | 115 - .../components/ui/PillSelect/PillButton.tsx | 59 - .../components/ui/PillSelect/PillSelect.tsx | 54 - .../ui/PillSelect/index.stories.tsx | 82 - .../src/components/ui/PillSelect/index.ts | 2 - .../src/components/ui/Popout/Popout.tsx | 89 - .../components/ui/Popout/index.stories.tsx | 45 - .../src/components/ui/Popout/index.tsx | 1 - .../components/ui/ProgressBar/ProgressBar.tsx | 75 - .../ui/ProgressBar/index.stories.tsx | 17 - .../src/components/ui/ProgressBar/index.tsx | 1 - .../components/ui/RadioButton/RadioButton.tsx | 44 - .../ui/RadioButton/index.stories.tsx | 17 - .../src/components/ui/RadioButton/index.tsx | 1 - .../ResizablePanels.module.scss | 87 - .../ui/ResizablePanels/ResizablePanels.tsx | 118 - .../components/ui/ResizablePanels/index.tsx | 1 - .../SecretTextArea/SecretTextArea.module.scss | 21 - .../ui/SecretTextArea/SecretTextArea.test.tsx | 85 - .../ui/SecretTextArea/SecretTextArea.tsx | 93 - .../ui/SecretTextArea/index.stories.tsx | 27 - .../src/components/ui/SecretTextArea/index.ts | 1 - .../src/components/ui/SideMenu/MenuItem.tsx | 48 - .../src/components/ui/SideMenu/SideMenu.tsx | 66 - .../components/ui/SideMenu/index.stories.tsx | 54 - .../src/components/ui/SideMenu/index.tsx | 1 - .../ui/SlickSlider/SlickSlider.module.scss | 46 - .../components/ui/SlickSlider/SlickSlider.tsx | 71 - .../ui/SlickSlider/index.stories.tsx | 43 - .../src/components/ui/SlickSlider/index.ts | 1 - .../src/components/ui/SlickSlider/slider.css | 19 - .../components/ui/Spinner/Spinner.module.scss | 25 - .../components/ui/Spinner/Spinner.test.tsx | 11 - .../src/components/ui/Spinner/Spinner.tsx | 12 - .../__snapshots__/Spinner.test.tsx.snap | 11 - .../components/ui/Spinner/index.stories.tsx | 15 - .../src/components/ui/Spinner/index.tsx | 1 - .../ui/StatusIcon/CircleLoader.module.scss | 24 - .../components/ui/StatusIcon/CircleLoader.tsx | 34 - .../ui/StatusIcon/StatusIcon.test.tsx | 42 - .../components/ui/StatusIcon/StatusIcon.tsx | 100 - .../ui/StatusIcon/index.stories.tsx | 18 - .../src/components/ui/StatusIcon/index.ts | 1 - .../StepsIndicator/StepsIndicator.module.scss | 31 - .../ui/StepsIndicator/StepsIndicator.tsx | 51 - .../ui/StepsIndicator/index.stories.tsx | 30 - .../src/components/ui/StepsIndicator/index.ts | 1 - .../src/components/ui/StepsMenu/Step.tsx | 74 - .../src/components/ui/StepsMenu/StepsMenu.tsx | 44 - .../components/ui/StepsMenu/index.stories.tsx | 30 - .../src/components/ui/StepsMenu/index.tsx | 1 - .../src/components/ui/Switch/Progress.svg | 31 - .../components/ui/Switch/ProgressReverse.svg | 31 - .../components/ui/Switch/Switch.module.scss | 161 - .../components/ui/Switch/Switch.stories.tsx | 18 - .../src/components/ui/Switch/Switch.tsx | 57 - .../src/components/ui/Switch/index.tsx | 1 - .../SortableTableHeader.module.scss | 14 - .../ui/Table/SortableTableHeader/index.tsx | 23 - .../src/components/ui/Table/Table.module.scss | 95 - .../src/components/ui/Table/Table.tsx | 115 - .../src/components/ui/Table/index.stories.tsx | 44 - .../src/components/ui/Table/index.ts | 2 - .../ui/TagInput/TagInput.module.scss | 14 - .../components/ui/TagInput/TagInput.test.tsx | 95 - .../src/components/ui/TagInput/TagInput.tsx | 166 - .../src/components/ui/TagInput/index.tsx | 1 - .../src/components/ui/Text/Text.tsx | 63 - .../src/components/ui/Text/index.stories.tsx | 17 - .../src/components/ui/Text/index.ts | 1 - .../src/components/ui/Text/text.module.scss | 54 - .../ui/TextArea/TextArea.module.scss | 52 - .../src/components/ui/TextArea/TextArea.tsx | 31 - .../components/ui/TextArea/index.stories.tsx | 15 - .../src/components/ui/TextArea/index.tsx | 1 - .../TextInputContainer.module.scss | 70 - .../TextInputContainer/TextInputContainer.tsx | 45 - .../ui/TextInputContainer/index.stories.tsx | 20 - .../components/ui/TextInputContainer/index.ts | 1 - .../ui/TextWithHTML/TextWithHTML.tsx | 33 - .../ui/TextWithHTML/index.stories.tsx | 24 - .../src/components/ui/TextWithHTML/index.tsx | 1 - .../src/components/ui/Toast/Toast.module.scss | 95 - .../src/components/ui/Toast/Toast.tsx | 72 - .../src/components/ui/Toast/index.stories.tsx | 76 - .../src/components/ui/Toast/index.tsx | 1 - .../ui/Tooltip/InfoTooltip.module.scss | 20 - .../src/components/ui/Tooltip/InfoTooltip.tsx | 24 - .../components/ui/Tooltip/Tooltip.module.scss | 35 - .../src/components/ui/Tooltip/Tooltip.tsx | 105 - .../Tooltip/TooltipLearnMoreLink.module.scss | 5 - .../ui/Tooltip/TooltipLearnMoreLink.tsx | 15 - .../ui/Tooltip/TooltipTable.module.scss | 13 - .../components/ui/Tooltip/TooltipTable.tsx | 24 - .../src/components/ui/Tooltip/context.ts | 15 - .../components/ui/Tooltip/index.stories.tsx | 57 - .../src/components/ui/Tooltip/index.ts | 6 - .../src/components/ui/Tooltip/types.ts | 18 - .../src/config/ConfigServiceProvider.tsx | 27 - .../src/config/availableCronTimeZones.json | 559 - airbyte-webapp/src/config/casesConfig.json | 7 - airbyte-webapp/src/config/config.ts | 42 - airbyte-webapp/src/config/frequencyConfig.ts | 32 - airbyte-webapp/src/config/index.ts | 3 - airbyte-webapp/src/config/types.ts | 54 - airbyte-webapp/src/core/ApiServices.tsx | 29 - .../core/analytics/AnalyticsService.test.ts | 70 - .../src/core/analytics/AnalyticsService.ts | 45 - airbyte-webapp/src/core/analytics/index.ts | 2 - airbyte-webapp/src/core/analytics/types.ts | 63 - airbyte-webapp/src/core/analytics/utils.ts | 13 - .../src/core/domain/Documentation.test.ts | 14 - .../src/core/domain/Documentation.ts | 13 - airbyte-webapp/src/core/domain/catalog/api.ts | 18 - .../src/core/domain/catalog/index.tsx | 3 - .../src/core/domain/catalog/models.ts | 20 - .../catalog/traverseSchemaToField.test.ts | 106 - .../domain/catalog/traverseSchemaToField.ts | 49 - .../domain/connection/ConnectionService.ts | 24 - .../domain/connection/OperationService.ts | 15 - .../connection/WebBackendConnectionService.ts | 28 - .../src/core/domain/connection/index.ts | 5 - .../src/core/domain/connection/operation.ts | 14 - .../src/core/domain/connection/types.ts | 7 - .../src/core/domain/connection/utils.ts | 25 - .../connector/DestinationAuthService.ts | 17 - .../connector/DestinationDefinitionService.ts | 34 - ...stinationDefinitionSpecificationService.ts | 8 - .../domain/connector/DestinationService.ts | 81 - .../domain/connector/SourceAuthService.ts | 17 - .../connector/SourceDefinitionService.ts | 34 - .../SourceDefinitionSpecificationService.ts | 8 - .../core/domain/connector/SourceService.ts | 102 - .../src/core/domain/connector/connector.ts | 36 - .../src/core/domain/connector/constants.ts | 40 - .../src/core/domain/connector/destination.ts | 13 - .../src/core/domain/connector/index.ts | 2 - .../src/core/domain/connector/source.ts | 38 - .../src/core/domain/connector/types.ts | 22 - .../ConnectorBuilderRequestService.ts | 30 - airbyte-webapp/src/core/domain/job/Job.ts | 9 - .../src/core/domain/job/JobsService.tsx | 20 - airbyte-webapp/src/core/domain/job/index.ts | 2 - .../src/core/domain/logs/LogsService.tsx | 8 - airbyte-webapp/src/core/domain/logs/types.ts | 4 - .../notification/NotificationService.tsx | 8 - .../src/core/domain/workspace/Workspace.ts | 28 - .../core/domain/workspace/WorkspaceService.ts | 28 - .../src/core/domain/workspace/index.ts | 2 - .../src/core/form/FormBuildError.ts | 11 - airbyte-webapp/src/core/form/FormikPatch.ts | 29 - .../src/core/form/schemaToFormBlock.test.ts | 325 - .../src/core/form/schemaToFormBlock.ts | 171 - .../src/core/form/schemaToYup.test.ts | 226 - airbyte-webapp/src/core/form/schemaToYup.ts | 226 - airbyte-webapp/src/core/form/types.ts | 63 - .../src/core/health/HealthService.ts | 8 - .../src/core/i18n/I18nProvider.test.tsx | 81 - airbyte-webapp/src/core/i18n/I18nProvider.tsx | 56 - airbyte-webapp/src/core/i18n/index.ts | 1 - airbyte-webapp/src/core/jsonSchema/types.ts | 27 - .../src/core/request/AirbyteRequestService.ts | 85 - .../src/core/request/CommonRequestError.ts | 19 - .../src/core/request/LogsRequestError.ts | 22 - .../src/core/request/RequestMiddleware.ts | 1 - .../src/core/request/ServerError.ts | 3 - .../src/core/request/VersionError.ts | 9 - .../src/core/request/apiOverride.ts | 107 - .../src/core/request/pollUntil.test.ts | 67 - airbyte-webapp/src/core/request/pollUntil.ts | 20 - airbyte-webapp/src/core/servicesProvider.tsx | 66 - airbyte-webapp/src/dayjs-setup.ts | 12 - .../connection/useConfirmCatalogDiff.tsx | 29 - .../connection/useDestinationNamespace.ts | 24 - .../connection/useNewTableDesignExperiment.ts | 4 - .../src/hooks/connection/useSchemaChanges.ts | 21 - .../useAvailableConnectorDefinitions.ts | 20 - airbyte-webapp/src/hooks/router/useBlocker.ts | 40 - .../services/Analytics/__mocks__/index.ts | 1 - .../__mocks__/useAnalyticsService.tsx | 14 - .../src/hooks/services/Analytics/index.tsx | 2 - .../services/Analytics/pageTrackingCodes.tsx | 33 - .../Analytics/useAnalyticsService.tsx | 67 - .../AppMonitoringService.tsx | 59 - .../__mocks__/AppMonitoringService.tsx | 6 - .../AppMonitoringService/__mocks__/index.ts | 1 - .../AppMonitoringService/actionCodes.ts | 11 - .../services/AppMonitoringService/index.ts | 4 - .../BulkEdit/BulkEditService.test.tsx | 237 - .../services/BulkEdit/BulkEditService.tsx | 99 - .../ConfirmationModalService.tsx | 75 - .../hooks/services/ConfirmationModal/index.ts | 1 - .../services/ConfirmationModal/reducer.ts | 31 - .../hooks/services/ConfirmationModal/types.ts | 13 - .../ConnectionEditService.test.tsx | 211 - .../ConnectionEdit/ConnectionEditService.tsx | 150 - .../ConnectionFormService.test.tsx | 147 - .../ConnectionForm/ConnectionFormService.tsx | 153 - .../Experiment/ExperimentService.test.tsx | 72 - .../services/Experiment/ExperimentService.tsx | 45 - .../hooks/services/Experiment/experiments.ts | 29 - .../src/hooks/services/Experiment/index.ts | 2 - .../services/Feature/FeatureService.test.tsx | 218 - .../hooks/services/Feature/FeatureService.tsx | 125 - .../src/hooks/services/Feature/constants.ts | 17 - .../src/hooks/services/Feature/index.tsx | 3 - .../src/hooks/services/Feature/types.tsx | 18 - .../FormChangeTrackerService.tsx | 33 - .../services/FormChangeTracker/hooks.test.ts | 52 - .../hooks/services/FormChangeTracker/hooks.ts | 47 - .../hooks/services/FormChangeTracker/index.ts | 2 - .../hooks/services/FormChangeTracker/types.ts | 6 - .../services/Health/HealthPollService.tsx | 48 - .../src/hooks/services/Health/index.tsx | 1 - .../services/Modal/ModalService.test.tsx | 92 - .../src/hooks/services/Modal/ModalService.tsx | 67 - .../src/hooks/services/Modal/index.ts | 1 - .../src/hooks/services/Modal/types.ts | 23 - .../Notification/NotificationService.tsx | 87 - .../src/hooks/services/Notification/index.ts | 2 - .../hooks/services/Notification/reducer.ts | 51 - .../src/hooks/services/Notification/types.ts | 16 - .../src/hooks/services/useBuildUpdateCheck.ts | 57 - .../src/hooks/services/useConnectionHook.tsx | 304 - .../src/hooks/services/useConnector.tsx | 153 - .../src/hooks/services/useConnectorAuth.tsx | 222 - .../src/hooks/services/useDestinationHook.tsx | 156 - .../src/hooks/services/useDocumentation.ts | 38 - .../hooks/services/useRequestConnector.tsx | 32 - .../src/hooks/services/useSourceHook.tsx | 201 - .../src/hooks/services/useWorkspace.tsx | 109 - airbyte-webapp/src/hooks/useDeleteModal.tsx | 28 - airbyte-webapp/src/hooks/useLoadingState.tsx | 48 - airbyte-webapp/src/hooks/useQuery.ts | 8 - airbyte-webapp/src/hooks/useSegment.tsx | 25 - .../src/hooks/useTypesafeReducer.ts | 30 - airbyte-webapp/src/index.tsx | 28 - airbyte-webapp/src/locales/en.json | 781 - airbyte-webapp/src/packages/cloud/App.tsx | 82 - airbyte-webapp/src/packages/cloud/README.md | 16 - .../src/packages/cloud/cloudRoutePaths.tsx | 18 - .../src/packages/cloud/cloudRoutes.tsx | 149 - .../EnrollmentModal.module.scss | 53 - .../EnrollmentModal/EnrollmentModal.tsx | 155 - .../EnrollmentModal/cards.svg | 24 - .../EnrollmentModal/connectorGrid.svg | 439 - .../EnrollmentModal/free-alpha-beta-pills.svg | 34 - .../EnrollmentModal/free.svg | 13 - .../EnrollmentModal/index.ts | 1 - .../EnrollmentModal/mail.svg | 14 - .../useShowEnrollmentModal.tsx | 46 - .../FreeConnectorProgram/FreeTag.module.scss | 13 - .../FreeConnectorProgram/FreeTag.tsx | 23 - .../InlineEnrollmentCallout.module.scss | 26 - .../InlineEnrollmentCallout.tsx | 47 - .../LargeEnrollmentCallout.module.scss | 24 - .../LargeEnrollmentCallout.tsx | 44 - .../connectors-badges.svg | 22 - .../hooks/useFreeConnectorProgram.ts | 82 - .../experiments/FreeConnectorProgram/index.ts | 2 - .../FreeConnectorProgram/lib/api.ts | 36 - .../FreeConnectorProgram/lib/model.ts | 3 - .../longtail-connectors.svg | 667 - .../CountDownTimer/CountDownTimer.module.scss | 14 - .../CountDownTimer/CountDownTimer.tsx | 14 - .../SpeedyConnection/CountDownTimer/index.ts | 1 - .../CountDownTimer/useCountdown.ts | 25 - .../SpeedyConnectionBanner.module.scss | 40 - .../SpeedyConnectionBanner.tsx | 34 - .../SpeedyConnectionBanner/credits.svg | 196 - .../SpeedyConnectionBanner/index.ts | 1 - .../hooks/useExperimentSpeedyConnection.ts | 15 - .../packages/cloud/lib/auth/AuthProviders.ts | 5 - .../cloud/lib/auth/GoogleAuthService.ts | 179 - .../cloud/lib/auth/RequestAuthMiddleware.ts | 16 - .../cloudWorkspaces/CloudWorkspacesService.ts | 70 - .../cloud/lib/domain/cloudWorkspaces/types.ts | 42 - .../packages/cloud/lib/domain/dbtCloud/api.ts | 55 - .../cloud/lib/domain/dbtCloud/index.ts | 1 - .../domain/geographies/GeographiesService.ts | 8 - .../cloud/lib/domain/speakeasy/api.ts | 22 - .../cloud/lib/domain/speakeasy/index.ts | 1 - .../cloud/lib/domain/stripe/StripeService.ts | 13 - .../packages/cloud/lib/domain/stripe/index.ts | 2 - .../packages/cloud/lib/domain/stripe/types.ts | 11 - .../cloud/lib/domain/users/UserService.ts | 97 - .../packages/cloud/lib/domain/users/index.ts | 2 - .../packages/cloud/lib/domain/users/types.ts | 20 - .../packages/cloud/lib/errors/FieldError.tsx | 5 - .../src/packages/cloud/locales/en.json | 204 - .../src/packages/cloud/package.json | 19 - .../cloud/services/AppServicesProvider.tsx | 65 - .../cloud/services/FirebaseSdkProvider.tsx | 32 - .../cloud/services/auth/AuthService.tsx | 355 - .../cloud/services/auth/freeEmailProviders.ts | 3752 ---- .../packages/cloud/services/auth/reducer.ts | 77 - .../src/packages/cloud/services/auth/types.ts | 11 - .../src/packages/cloud/services/dbtCloud.ts | 163 - .../geographies/GeographiesService.ts | 29 - .../cloud/services/speakeasy/index.ts | 1 - .../speakeasy/useSpeakeasyRedirect.ts | 20 - .../cloud/services/stripe/StripeService.tsx | 22 - .../thirdParty/intercom/IntercomProvider.tsx | 15 - .../services/thirdParty/intercom/index.tsx | 1 - .../thirdParty/intercom/useIntercom.ts | 39 - .../launchdarkly/LDExperimentService.tsx | 216 - .../services/thirdParty/launchdarkly/index.ts | 1 - .../users/InviteUsersModalService.tsx | 44 - .../cloud/services/users/UseUserHook.ts | 51 - .../cloud/services/users/UserService.tsx | 15 - .../workspaces/CloudWorkspacesService.ts | 130 - airbyte-webapp/src/packages/cloud/theme.ts | 26 - .../cloud/views/AcceptEmailInvite.tsx | 98 - .../src/packages/cloud/views/DefaultView.tsx | 21 - .../cloud/views/FirebaseActionRoute.tsx | 72 - .../cloud/views/auth/Auth.module.scss | 42 - .../src/packages/cloud/views/auth/Auth.tsx | 83 - .../ConfirmPasswordResetPage.tsx | 129 - .../auth/ConfirmPasswordResetPage/index.tsx | 5 - .../auth/LoginPage/LoginPage.module.scss | 3 - .../cloud/views/auth/LoginPage/LoginPage.tsx | 122 - .../cloud/views/auth/LoginPage/index.tsx | 1 - .../auth/OAuthLogin/OAuthLogin.module.scss | 54 - .../views/auth/OAuthLogin/OAuthLogin.test.tsx | 43 - .../views/auth/OAuthLogin/OAuthLogin.tsx | 98 - .../auth/OAuthLogin/assets/github-logo.svg | 23 - .../auth/OAuthLogin/assets/google-logo.svg | 63 - .../cloud/views/auth/OAuthLogin/index.ts | 1 - .../ResetPasswordPage/ResetPasswordPage.tsx | 91 - .../views/auth/ResetPasswordPage/index.tsx | 3 - .../auth/SignupPage/SignupPage.module.scss | 11 - .../views/auth/SignupPage/SignupPage.tsx | 54 - .../components/Separator.module.scss | 28 - .../auth/SignupPage/components/Separator.tsx | 10 - .../components/SignupForm.module.scss | 27 - .../auth/SignupPage/components/SignupForm.tsx | 280 - .../SimpleLeftSide/SimpleLeftSide.module.scss | 11 - .../SimpleLeftSide/SimpleLeftSide.tsx | 64 - .../components/SpecialBlock.module.scss | 16 - .../SignupPage/components/SpecialBlock.tsx | 20 - .../cloud/views/auth/SignupPage/index.tsx | 3 - .../views/auth/components/CheckBoxControl.tsx | 33 - .../views/auth/components/FormComponents.tsx | 33 - .../views/auth/components/FormContent.tsx | 40 - .../FormTitle/FormTitle.module.scss | 5 - .../auth/components/FormTitle/FormTitle.tsx | 11 - .../views/auth/components/FormTitle/index.tsx | 1 - .../components/GitBlock/GitBlock.module.scss | 41 - .../components/GitBlock/GitBlock.test.tsx | 33 - .../auth/components/GitBlock/GitBlock.tsx | 32 - .../__snapshots__/GitBlock.test.tsx.snap | 101 - .../views/auth/components/GitBlock/index.tsx | 1 - .../auth/components/Header/Header.module.scss | 21 - .../views/auth/components/Header/Header.tsx | 29 - .../views/auth/components/Header/index.tsx | 1 - .../PersonQuoteCover.module.scss | 96 - .../PersonQuoteCover/PersonQuoteCover.tsx | 34 - .../components/PersonQuoteCover/index.tsx | 3 - .../src/packages/cloud/views/auth/index.tsx | 3 - .../CreditsPage/CreditsPage.module.scss | 18 - .../views/credits/CreditsPage/CreditsPage.tsx | 51 - .../components/ConnectionCell.module.scss | 10 - .../CreditsPage/components/ConnectionCell.tsx | 44 - .../components/CreditsUsage.module.scss | 16 - .../CreditsPage/components/CreditsUsage.tsx | 70 - .../components/EmailVerificationHint.tsx | 51 - .../LowCreditBalanceHint.module.scss | 12 - .../LowCreditBalanceHint.tsx | 41 - .../components/LowCreditBalanceHint/index.tsx | 1 - .../components/RemainingCredits.tsx | 167 - .../CreditsPage/components/UsageCell.tsx | 30 - .../UsagePerConnectionTable.module.scss | 41 - .../components/UsagePerConnectionTable.tsx | 176 - .../cloud/views/credits/CreditsPage/index.tsx | 3 - .../packages/cloud/views/credits/index.tsx | 3 - .../CloudMainView/CloudMainView.module.scss | 66 - .../layout/CloudMainView/CloudMainView.tsx | 142 - .../CloudMainView/CloudResourcesDropdown.tsx | 46 - .../CloudMainView/CloudSupportDropdown.tsx | 38 - .../InsufficientPermissionsErrorBoundary.tsx | 40 - .../views/layout/CloudMainView/index.tsx | 3 - .../views/settings/CloudSettingsPage.tsx | 122 - .../DbtCloudSettingsView.module.scss | 27 - .../integrations/DbtCloudSettingsView.tsx | 79 - .../cloud/views/settings/routePaths.ts | 14 - .../AccountSettingsView.tsx | 44 - .../components/EmailSection/EmailSection.tsx | 113 - .../components/EmailSection/hooks/index.ts | 1 - .../components/EmailSection/hooks/useEmail.ts | 71 - .../components/EmailSection/index.ts | 1 - .../components/EmailSection/typings.d.ts | 4 - .../components/NameSection/NameSection.tsx | 67 - .../components/NameSection/hooks/index.ts | 1 - .../components/NameSection/hooks/useName.ts | 47 - .../components/NameSection/index.ts | 1 - .../components/NameSection/types.ts | 3 - .../PasswordSection/PasswordSection.tsx | 89 - .../components/PasswordSection/hooks/index.ts | 1 - .../PasswordSection/hooks/usePassword.ts | 101 - .../components/PasswordSection/index.ts | 1 - .../components/PasswordSection/typings.d.ts | 5 - .../AccountSettingsView/components/index.ts | 3 - .../views/users/AccountSettingsView/index.tsx | 1 - .../InviteUsersHint.module.scss | 14 - .../InviteUsersHint/InviteUsersHint.test.tsx | 77 - .../users/InviteUsersHint/InviteUsersHint.tsx | 67 - .../views/users/InviteUsersHint/index.ts | 1 - .../views/users/InviteUsersHint/types.ts | 3 - .../InviteUsersModal.module.scss | 8 - .../InviteUsersModal/InviteUsersModal.tsx | 205 - .../views/users/InviteUsersModal/index.tsx | 1 - .../views/users/InviteUsersModal/types.ts | 6 - .../UsersSettingsView.module.scss | 5 - .../UsersSettingsView/UsersSettingsView.tsx | 124 - .../components/RoleToolTip.tsx | 39 - .../views/users/UsersSettingsView/index.tsx | 1 - .../DataResidencyView.module.scss | 39 - .../DataResidencyView/DataResidencyView.tsx | 119 - .../workspaces/DataResidencyView/index.ts | 1 - .../WorkspacePopout/WorkspacePopout.tsx | 138 - .../WorkspacePopout/components/ExitIcon.tsx | 10 - .../workspaces/WorkspacePopout/index.tsx | 1 - .../WorkspaceSettingsView.module.scss | 20 - .../WorkspaceSettingsView.tsx | 108 - .../WorkspaceSettingsView/index.tsx | 1 - .../WorkspacesPage/WorkspacesPage.module.scss | 16 - .../WorkspacesPage/WorkspacesPage.tsx | 31 - .../components/CreateWorkspaceForm.tsx | 65 - .../components/WorkspaceControl.module.scss | 3 - .../components/WorkspaceItem.module.scss | 22 - .../components/WorkspaceItem.tsx | 16 - .../components/WorkspacesControl.tsx | 37 - .../components/WorkspacesList.tsx | 37 - .../views/workspaces/WorkspacesPage/index.tsx | 3 - .../packages/cloud/views/workspaces/index.tsx | 3 - .../packages/firebaseReact/firebaseApp.tsx | 66 - .../src/packages/firebaseReact/index.tsx | 2 - .../src/packages/firebaseReact/sdk.tsx | 38 - .../PreferencesPage.module.scss | 3 - .../pages/PreferencesPage/PreferencesPage.tsx | 30 - .../src/pages/PreferencesPage/index.tsx | 3 - .../SettingsPage/SettingsPage.module.scss | 11 - .../src/pages/SettingsPage/SettingsPage.tsx | 115 - .../SettingsPage/components/FeedbackBlock.tsx | 45 - .../components/useWorkspaceEditor.tsx | 49 - .../src/pages/SettingsPage/index.tsx | 3 - .../pages/AccountPage/AccountPage.tsx | 48 - .../components/AccountForm.module.scss | 7 - .../AccountPage/components/AccountForm.tsx | 97 - .../SettingsPage/pages/AccountPage/index.tsx | 3 - .../ConfigurationsPage/ConfigurationsPage.tsx | 20 - .../ImportConfigurationModal.module.scss | 3 - .../components/LogsContainer.module.scss | 3 - .../components/LogsContent.tsx | 66 - .../pages/ConfigurationsPage/index.tsx | 3 - .../pages/ConnectorsPage/DestinationsPage.tsx | 98 - .../pages/ConnectorsPage/SourcesPage.tsx | 94 - .../components/ConnectorCell.module.scss | 3 - .../components/ConnectorCell.tsx | 30 - .../components/ConnectorsView.module.scss | 25 - .../components/ConnectorsView.tsx | 201 - .../components/ConnectorsViewContext.tsx | 18 - .../components/CreateConnector.tsx | 130 - .../CreateConnectorModal.module.scss | 10 - .../components/CreateConnectorModal.tsx | 190 - .../components/ImageCell.module.scss | 13 - .../ConnectorsPage/components/ImageCell.tsx | 31 - .../components/UpgradeAllButton.module.scss | 3 - .../components/UpgradeAllButton.tsx | 63 - .../components/VersionCell.module.scss | 34 - .../ConnectorsPage/components/VersionCell.tsx | 82 - .../components/builder-icon.svg | 3 - .../pages/ConnectorsPage/index.tsx | 4 - .../pages/MetricsPage/MetricsPage.tsx | 40 - .../MetricsPage/components/MetricsForm.tsx | 86 - .../SettingsPage/pages/MetricsPage/index.tsx | 3 - .../NotificationPage/NotificationPage.tsx | 32 - .../components/NotificationsForm.tsx | 89 - .../components/WebHookForm.module.scss | 168 - .../components/WebHookForm.tsx | 276 - .../NotificationPage/components/help.png | Bin 31497 -> 0 bytes .../pages/NotificationPage/index.tsx | 3 - .../SettingsPage/pages/SettingsComponents.tsx | 15 - .../src/pages/SourcesPage/SourcesPage.tsx | 29 - .../src/pages/SourcesPage/index.tsx | 3 - .../pages/AllSourcesPage/AllSourcesPage.tsx | 44 - .../components/SourcesTable.tsx | 27 - .../pages/AllSourcesPage/index.tsx | 3 - .../CreateSourcePage/CreateSourcePage.tsx | 55 - .../components/SourceForm.module.scss | 6 - .../components/SourceForm.tsx | 87 - .../pages/SourceItemPage/SourceItemPage.tsx | 128 - .../SourceConnectionTable.module.scss | 5 - .../components/SourceConnectionTable.tsx | 32 - .../components/SourceSettings.module.scss | 7 - .../components/SourceSettings.tsx | 94 - .../pages/SourceItemPage/index.tsx | 3 - .../SpeakeasyRedirectPage.tsx | 71 - .../src/pages/SpeakeasyRedirectPage/index.tsx | 3 - .../AllConnectionsPage.module.scss | 10 - .../AllConnectionsPage/AllConnectionsPage.tsx | 57 - .../AllConnectionsPage/ConnectionsTable.tsx | 24 - .../connections/AllConnectionsPage/index.ts | 3 - .../ConnectionPage/ConnectionPage.tsx | 54 - .../ConnectionPageTitle.module.scss | 25 - .../ConnectionPage/ConnectionPageTitle.tsx | 91 - .../pages/connections/ConnectionPage/index.ts | 3 - .../ConnectionReplicationPage.module.scss | 9 - .../ConnectionReplicationPage.test.tsx | 175 - .../ConnectionReplicationPage.tsx | 213 - .../ResetWarningModal.tsx | 59 - .../ConnectionReplicationPage.test.tsx.snap | 1032 - .../ConnectionReplicationPage/index.ts | 1 - .../ConnectionSettingsPage.module.scss | 15 - .../ConnectionSettingsPage.tsx | 66 - .../SchemaUpdateNotifications.module.scss | 8 - .../SchemaUpdateNotifications.tsx | 49 - .../ConnectionSettingsPage/StateBlock.tsx | 44 - .../ConnectionSettingsPage/index.ts | 1 - .../ConnectionStatusPage.module.scss | 26 - .../ConnectionStatusPage.tsx | 209 - .../ConnectionStatusPage/JobsList.tsx | 28 - .../connections/ConnectionStatusPage/index.ts | 1 - .../ConnectionTransformationPage.module.scss | 24 - .../ConnectionTransformationPage.tsx | 78 - .../CustomTransformationsCard.tsx | 50 - .../DbtCloudTransformationsCard.tsx | 102 - .../DbtCloudCard.scss | 24 - .../DbtCloudTransformationsCard.module.scss | 1 - .../DbtJobsForm.module.scss | 5 - .../DbtJobsForm.tsx | 91 - .../JobsList.module.scss | 20 - .../DbtCloudTransformationsCard/JobsList.tsx | 56 - .../JobsListItem.module.scss | 60 - .../JobsListItem.tsx | 60 - .../NoDbtIntegration.module.scss | 1 - .../NoDbtIntegration.tsx | 37 - .../dbt-bit_tm.svg | 5 - .../octavia-worker.png | Bin 14408 -> 0 bytes .../NormalizationCard.tsx | 38 - .../ConnectionTransformationPage/index.ts | 1 - .../pages/connections/ConnectionsRoutes.tsx | 33 - .../ConnectionCreateDestinationForm.tsx | 56 - .../ConnectionCreateSourceForm.tsx | 54 - .../CreateConnectionPage.tsx | 246 - .../ExistingEntityForm.module.scss | 12 - .../ExistingEntityForm.tsx | 118 - .../connections/CreateConnectionPage/index.ts | 1 - airbyte-webapp/src/pages/connections/types.ts | 7 - .../ConnectorBuilderEditPage.module.scss | 23 - .../ConnectorBuilderEditPage.tsx | 123 - .../ConnectorBuilderEditPage/index.ts | 1 - .../ConnectorBuilderLandingPage.module.scss | 32 - .../ConnectorBuilderLandingPage.tsx | 255 - .../airbyte-logo.svg | 4 - .../import-yaml.svg | 155 - .../ConnectorBuilderLandingPage/index.ts | 1 - .../load-existing-connector.svg | 352 - .../start-from-scratch.svg | 223 - .../ConnectorBuilderRoutes.tsx | 24 - .../AllDestinationsPage.tsx | 49 - .../destination/AllDestinationsPage/index.tsx | 1 - .../CreateDestinationPage.tsx | 51 - .../CreateDestinationPage/index.tsx | 3 - .../DestinationItemPage.tsx | 56 - .../destination/DestinationItemPage/index.tsx | 1 - .../destination/DestinationOverviewPage.tsx | 75 - .../DestinationSettings.module.scss | 7 - .../DestinationSettingsPage.tsx | 88 - .../DestinationSettingsPage/index.ts | 1 - airbyte-webapp/src/pages/destination/types.ts | 5 - airbyte-webapp/src/pages/routePaths.tsx | 27 - airbyte-webapp/src/pages/routes.tsx | 115 - airbyte-webapp/src/scss/_colors.scss | 108 - airbyte-webapp/src/scss/_fonts.scss | 2 - airbyte-webapp/src/scss/_mixins.scss | 13 - airbyte-webapp/src/scss/_theme-light.scss | 99 - airbyte-webapp/src/scss/_variables.scss | 43 - airbyte-webapp/src/scss/_z-indices.scss | 10 - airbyte-webapp/src/scss/export.module.scss | 113 - airbyte-webapp/src/scss/global.scss | 28 - airbyte-webapp/src/services/Scope.ts | 2 - .../connector/ConnectorDefinitions.ts | 45 - .../services/connector/ConnectorService.ts | 46 - .../connector/DestinationDefinitionService.ts | 132 - ...tinationDefinitionSpecificationService.tsx | 44 - .../connector/SourceDefinitionService.ts | 124 - .../SourceDefinitionSpecificationService.tsx | 43 - .../services/connector/useSuspenseQuery.ts | 23 - .../ConnectorBuilderApiService.ts | 65 - .../ConnectorBuilderLocalStorageService.tsx | 85 - .../ConnectorBuilderStateService.tsx | 251 - .../connector_manifest_openapi.yaml | 9 - .../src/services/job/JobService.tsx | 91 - .../src/services/logs/LogsService.tsx | 26 - .../services/useDefaultRequestMiddlewares.tsx | 9 - .../src/services/useInitService.tsx | 18 - .../services/workspaces/WorkspacesService.tsx | 137 - .../src/test-utils/TestSuspenseBoundary.tsx | 5 - .../src/test-utils/classname-serializer.js | 36 - airbyte-webapp/src/test-utils/index.ts | 2 - .../mockAirbyteStreamConfiguration.ts | 9 - .../test-utils/mock-data/mockCatalogDiff.ts | 46 - .../test-utils/mock-data/mockConnection.ts | 357 - .../test-utils/mock-data/mockDestination.ts | 354 - .../mockDestinationDefinitionSpecification.ts | 276 - .../src/test-utils/mock-data/mockEmpty.js | 2 - .../mockFrequentlyUsedDestinations.ts | 67 - .../src/test-utils/mock-data/mockIdentity.js | 14 - .../src/test-utils/mock-data/mockSource.ts | 436 - .../mock-data/mockSourceDefinition.ts | 32 - .../mock-data/mockStartWithDestination.ts | 10 - .../src/test-utils/mock-data/mockSvg.js | 6 - .../src/test-utils/mock-data/mockWorkspace.ts | 15 - .../test-utils/mock-data/mockWorkspaceId.ts | 1 - airbyte-webapp/src/test-utils/setup-tests.ts | 22 - airbyte-webapp/src/test-utils/testutils.tsx | 130 - airbyte-webapp/src/theme.ts | 142 - airbyte-webapp/src/types/formik.ts | 3 - airbyte-webapp/src/types/react-widgets.d.ts | 3 - airbyte-webapp/src/types/rehype-urls.d.ts | 1 - .../useTranslateDataType.test.tsx.snap | 29 - airbyte-webapp/src/utils/app.ts | 1 - airbyte-webapp/src/utils/clipboard.ts | 3 - airbyte-webapp/src/utils/common.test.ts | 13 - airbyte-webapp/src/utils/common.ts | 3 - .../src/utils/connectors/constants.ts | 7 - .../src/utils/connectors/destinations.json | 50 - airbyte-webapp/src/utils/connectors/index.ts | 1 - .../src/utils/connectors/sources.json | 261 - airbyte-webapp/src/utils/cron/index.ts | 1 - .../utils/cron/validateCronExpression.test.ts | 87 - .../src/utils/cron/validateCronExpression.ts | 65 - .../src/utils/crossDomainUtils.test.ts | 19 - airbyte-webapp/src/utils/crossDomainUtils.ts | 27 - airbyte-webapp/src/utils/dataPrivacy.test.ts | 33 - airbyte-webapp/src/utils/dataPrivacy.ts | 90 - airbyte-webapp/src/utils/datadog.ts | 30 - .../src/utils/errorStatusMessage.test.tsx | 35 - .../src/utils/errorStatusMessage.tsx | 21 - airbyte-webapp/src/utils/file.ts | 10 - airbyte-webapp/src/utils/imageUtils.tsx | 26 - airbyte-webapp/src/utils/links.ts | 43 - .../src/utils/numberHelper.test.tsx | 35 - airbyte-webapp/src/utils/numberHelper.tsx | 19 - airbyte-webapp/src/utils/objects.ts | 13 - airbyte-webapp/src/utils/promises.ts | 8 - airbyte-webapp/src/utils/sentry.ts | 20 - airbyte-webapp/src/utils/strings.test.ts | 9 - airbyte-webapp/src/utils/strings.ts | 2 - .../src/utils/useTranslateDataType.test.tsx | 74 - .../src/utils/useTranslateDataType.ts | 56 - .../src/utils/withKeystrokeHandler.tsx | 38 - .../src/views/CompleteOauthRequest.tsx | 13 - .../ConnectorCard/ConnectorCard.module.scss | 17 - .../Connector/ConnectorCard/ConnectorCard.tsx | 263 - .../ConnectorCard/components/Controls.tsx | 76 - .../components/ShowLoadingMessage.tsx | 39 - .../components/TestCard.module.scss | 5 - .../ConnectorCard/components/TestCard.tsx | 121 - .../TestingConnectionSpinner.module.scss | 12 - .../components/TestingConnectionSpinner.tsx | 29 - .../components/TestingConnectionSuccess.tsx | 17 - .../views/Connector/ConnectorCard/index.tsx | 1 - .../useAnalyticsTrackFunctions.tsx | 48 - .../ConnectorCard/useTestConnector.tsx | 84 - .../ConnectorDocumentationLayout.module.scss | 15 - .../ConnectorDocumentationLayout.tsx | 48 - .../ConnectorDocumentationWrapper.tsx | 10 - .../DocumentationPanel.module.scss | 11 - .../DocumentationPanel.test.ts | 40 - .../DocumentationPanel.tsx | 76 - .../DocumentationPanelContext.tsx | 40 - .../ConnectorDocumentationLayout/index.ts | 1 - .../ConnectorForm/ConnectorForm.test.tsx | 395 - .../Connector/ConnectorForm/ConnectorForm.tsx | 116 - .../ConnectorForm/FormRoot.module.scss | 5 - .../Connector/ConnectorForm/FormRoot.tsx | 87 - .../ConnectorDefinitionTypeControl.tsx | 226 - .../ConnectorServiceTypeControl.module.scss | 62 - .../ConnectorServiceTypeControl/index.ts | 1 - .../useAnalyticsTrackFunctions.tsx | 40 - .../ConnectorServiceTypeControl/utils.tsx | 58 - .../FrequentlyUsedConnectors.tsx | 37 - .../FrequentlyUsedConnectorsCard.module.scss | 20 - .../FrequentlyUsedConnectorsCard.test.tsx | 39 - .../FrequentlyUsedConnectorsCard.tsx | 42 - ...FrequentlyUsedConnectorsCard.test.tsx.snap | 348 - .../index.stories.tsx | 27 - .../FrequentlyUsedConnectors/index.ts | 1 - .../useAnalyticsTrackFunctions.tsx | 21 - .../useSuggestedConnectors.ts | 48 - .../components/Property/Control.tsx | 155 - .../components/Property/LabelInfo.module.scss | 54 - .../components/Property/LabelInfo.tsx | 87 - .../Property/PropertyError.module.scss | 7 - .../components/Property/PropertyError.tsx | 9 - .../Property/PropertyLabel.stories.tsx | 79 - .../components/Property/PropertyLabel.tsx | 60 - .../SecretConfirmationControl.module.scss | 8 - .../Property/SecretConfirmationControl.tsx | 112 - .../components/Sections/ArraySection.tsx | 134 - .../Sections/ConditionSection.module.scss | 3 - .../components/Sections/ConditionSection.tsx | 92 - .../components/Sections/FormSection.tsx | 81 - .../components/Sections/GroupLabel.tsx | 11 - .../Sections/PropertySection.module.scss | 12 - .../components/Sections/PropertySection.tsx | 59 - .../Sections/SectionContainer.module.scss | 9 - .../components/Sections/SectionContainer.tsx | 5 - .../Sections/VariableInputFieldForm.tsx | 83 - .../Sections/auth/AuthButton.module.scss | 19 - .../Sections/auth/AuthButton.test.tsx | 165 - .../components/Sections/auth/AuthButton.tsx | 96 - .../components/Sections/auth/AuthSection.tsx | 25 - .../Sections/auth/GoogleAuthButton.tsx | 50 - .../Sections/auth/useOauthFlowAdapter.tsx | 95 - .../components/TestingConnectionError.tsx | 35 - .../components/WarningMessage.module.scss | 15 - .../components/WarningMessage.tsx | 34 - .../ConnectorForm/connectorFormContext.tsx | 82 - .../Connector/ConnectorForm/index.stories.tsx | 220 - .../views/Connector/ConnectorForm/index.tsx | 2 - .../views/Connector/ConnectorForm/types.ts | 26 - .../ConnectorForm/useAuthentication.mocks.ts | 78 - .../ConnectorForm/useAuthentication.test.tsx | 197 - .../ConnectorForm/useAuthentication.tsx | 250 - .../Connector/ConnectorForm/useBuildForm.tsx | 156 - .../views/Connector/ConnectorForm/utils.ts | 37 - .../RequestConnectorModal.module.scss | 13 - .../RequestConnectorModal.tsx | 178 - .../Connector/RequestConnectorModal/index.tsx | 3 - .../Connector/RequestConnectorModal/types.ts | 6 - .../PreferencesForm/PreferencesForm.tsx | 202 - .../components/EditControls.tsx | 75 - .../views/Settings/PreferencesForm/index.tsx | 4 - .../src/views/common/AnalyticsProvider.tsx | 12 - .../ErrorOccurredView.module.scss | 27 - .../ErrorOccurredView/ErrorOccurredView.tsx | 48 - .../views/common/ErrorOccurredView/index.tsx | 1 - .../common/ResorceNotFoundErrorBoundary.tsx | 45 - .../src/views/common/StartOverErrorView.tsx | 25 - .../src/views/common/StoreProvider.tsx | 27 - .../layout/MainView/MainView.module.scss | 12 - .../src/views/layout/MainView/MainView.tsx | 62 - .../src/views/layout/MainView/index.tsx | 3 - .../SideBar/AirbyteHomeLink.module.scss | 5 - .../views/layout/SideBar/AirbyteHomeLink.tsx | 18 - .../src/views/layout/SideBar/MainNavItems.tsx | 48 - .../SideBar/NotificationIndicator.module.scss | 5 - .../layout/SideBar/NotificationIndicator.tsx | 13 - .../views/layout/SideBar/SideBar.module.scss | 29 - .../src/views/layout/SideBar/SideBar.tsx | 8 - .../src/views/layout/SideBar/airbyteLogo.svg | 3 - .../layout/SideBar/components/BuilderIcon.tsx | 10 - .../layout/SideBar/components/ChatIcon.tsx | 10 - .../SideBar/components/ConnectionsIcon.tsx | 12 - .../SideBar/components/DestinationIcon.tsx | 10 - .../components/MenuContent.module.scss | 12 - .../layout/SideBar/components/MenuContent.tsx | 17 - .../components/NavDropdown.module.scss | 30 - .../layout/SideBar/components/NavDropdown.tsx | 25 - .../SideBar/components/NavItem.module.scss | 43 - .../layout/SideBar/components/NavItem.tsx | 76 - .../layout/SideBar/components/RecipesIcon.tsx | 10 - .../SideBar/components/ResourcesDropdown.tsx | 40 - .../SideBar/components/SettingsIcon.tsx | 10 - .../layout/SideBar/components/SourceIcon.tsx | 9 - .../layout/SideBar/components/StatusIcon.tsx | 10 - airbyte-webapp/src/vite-env.d.ts | 1 - airbyte-webapp/tsconfig.json | 44 - airbyte-webapp/vite.config.ts | 87 - airbyte-workers/Dockerfile | 27 - airbyte-workers/README.md | 49 - airbyte-workers/build.gradle | 170 - airbyte-workers/gradle.properties | 1 - .../java/io/airbyte/workers/Application.java | 15 - .../workers/ApplicationInitializer.java | 405 - .../java/io/airbyte/workers/JobStatus.java | 14 - .../io/airbyte/workers/OutputAndStatus.java | 57 - .../io/airbyte/workers/SyncException.java | 7 - .../workers/config/ActivityBeanFactory.java | 210 - .../config/ApplicationBeanFactory.java | 155 - .../config/CloudStorageBeanFactory.java | 92 - ...ontainerOrchestratorConfigBeanFactory.java | 148 - .../workers/config/DatabaseBeanFactory.java | 144 - .../config/JobErrorReportingBeanFactory.java | 65 - .../config/ProcessFactoryBeanFactory.java | 226 - .../config/SecretPersistenceBeanFactory.java | 98 - .../workers/config/TemporalBeanFactory.java | 109 - .../WorkerConfigurationBeanFactory.java | 431 - .../controller/HeartbeatController.java | 54 - .../workers/run/TemporalWorkerRunFactory.java | 111 - .../io/airbyte/workers/run/WorkerRun.java | 59 - .../temporal/TemporalAttemptExecution.java | 251 - .../annotations/TemporalActivityStub.java | 30 - .../connection/CheckConnectionActivity.java | 38 - .../CheckConnectionActivityImpl.java | 160 - .../CheckConnectionWorkflowImpl.java | 54 - .../catalog/DiscoverCatalogActivity.java | 22 - .../catalog/DiscoverCatalogActivityImpl.java | 144 - .../catalog/DiscoverCatalogWorkflowImpl.java | 37 - .../ConnectionManagerWorkflowImpl.java | 797 - .../ConnectionNotificationWorkflowImpl.java | 53 - .../ConnectionUpdaterWorkflowConfig.java | 18 - .../temporal/scheduling/ManualSyncOutput.java | 16 - .../SyncCheckConnectionFailure.java | 83 - .../AutoDisableConnectionActivity.java | 46 - .../AutoDisableConnectionActivityImpl.java | 214 - .../activities/ConfigFetchActivity.java | 70 - .../activities/ConfigFetchActivityImpl.java | 304 - .../activities/GenerateInputActivity.java | 63 - .../activities/GenerateInputActivityImpl.java | 243 - .../JobCreationAndStatusUpdateActivity.java | 186 - ...obCreationAndStatusUpdateActivityImpl.java | 599 - .../NotifySchemaChangeActivity.java | 20 - .../NotifySchemaChangeActivityImpl.java | 35 - .../activities/RecordMetricActivity.java | 51 - .../activities/RecordMetricActivityImpl.java | 94 - .../RouteToSyncTaskQueueActivity.java | 38 - .../RouteToSyncTaskQueueActivityImpl.java | 45 - .../activities/SlackConfigActivity.java | 20 - .../activities/SlackConfigActivityImpl.java | 39 - .../activities/StreamResetActivity.java | 33 - .../activities/StreamResetActivityImpl.java | 38 - .../activities/WorkflowConfigActivity.java | 26 - .../WorkflowConfigActivityImpl.java | 39 - .../workers/temporal/spec/SpecActivity.java | 19 - .../temporal/spec/SpecActivityImpl.java | 137 - .../temporal/spec/SpecWorkflowImpl.java | 34 - ...TemporalActivityStubGeneratorFunction.java | 21 - .../TemporalActivityStubInterceptor.java | 171 - .../temporal/support/TemporalProxyHelper.java | 132 - .../sync/DbtTransformationActivity.java | 23 - .../sync/DbtTransformationActivityImpl.java | 175 - .../temporal/sync/NormalizationActivity.java | 35 - .../sync/NormalizationActivityImpl.java | 264 - .../NormalizationSummaryCheckActivity.java | 17 - ...NormalizationSummaryCheckActivityImpl.java | 93 - .../temporal/sync/PersistStateActivity.java | 19 - .../sync/PersistStateActivityImpl.java | 132 - .../temporal/sync/RefreshSchemaActivity.java | 19 - .../sync/RefreshSchemaActivityImpl.java | 86 - .../temporal/sync/ReplicationActivity.java | 24 - .../sync/ReplicationActivityImpl.java | 381 - .../temporal/sync/SyncOutputProvider.java | 39 - .../temporal/sync/SyncWorkflowImpl.java | 201 - .../sync/WebhookOperationActivity.java | 17 - .../sync/WebhookOperationActivityImpl.java | 91 - .../tracing/StorageObjectGetInterceptor.java | 51 - .../tracing/TemporalSdkInterceptor.java | 106 - .../airbyte/workers/utils/ConfigReplacer.java | 101 - .../resources/application-control-plane.yml | 44 - .../src/main/resources/application.yml | 265 - .../src/main/resources/micronaut-banner.txt | 8 - ...OrchestratorPodProcessIntegrationTest.java | 157 - .../KubePodProcessIntegrationTest.java | 466 - .../resources/application-test.yml | 11 - .../DefaultTaskQueueMapperTest.java | 43 - .../scheduling/RouterServiceTest.java | 60 - .../DefaultCheckConnectionWorkerTest.java | 278 - .../DefaultDiscoverCatalogWorkerTest.java | 301 - .../general/DefaultGetSpecWorkerTest.java | 152 - .../run/TemporalWorkerRunFactoryTest.java | 112 - .../io/airbyte/workers/run/WorkerRunTest.java | 39 - .../StreamResetRecordsHelperTest.java | 73 - .../TemporalAttemptExecutionTest.java | 146 - .../CheckConnectionWorkflowTest.java | 52 - .../ConnectionManagerWorkflowTest.java | 1613 -- .../ConnectionNotificationWorkflowTest.java | 113 - .../scheduling/WorkflowReplayingTest.java | 87 - .../AutoDisableConnectionActivityTest.java | 269 - .../activities/ConfigFetchActivityTest.java | 378 - .../activities/GenerateInputActivityTest.java | 253 - ...obCreationAndStatusUpdateActivityTest.java | 515 - ...NormalizationSummaryCheckActivityTest.java | 91 - .../NotifySchemaChangeActivityTest.java | 48 - .../RecordMetricActivityImplTest.java | 86 - .../activities/RefreshSchemaActivityTest.java | 78 - .../activities/SlackConfigActivityTest.java | 60 - .../activities/StreamResetActivityTest.java | 34 - .../WorkflowConfigActivityImplTest.java | 22 - .../DbtFailureSyncWorkflow.java | 33 - .../testsyncworkflow/EmptySyncWorkflow.java | 26 - .../NormalizationFailureSyncWorkflow.java | 33 - ...NormalizationTraceFailureSyncWorkflow.java | 42 - .../PersistFailureSyncWorkflow.java | 33 - .../ReplicateFailureSyncWorkflow.java | 33 - .../SleepingSyncWorkflow.java | 32 - ...urceAndDestinationFailureSyncWorkflow.java | 45 - .../SyncWorkflowFailingOutputWorkflow.java | 29 - ...owFailingWithHearbeatTimeoutException.java | 40 - ...cWorkflowWithActivityFailureException.java | 34 - .../temporal/stubs/ErrorTestWorkflowImpl.java | 24 - .../stubs/InvalidTestWorkflowImpl.java | 27 - .../workers/temporal/stubs/TestActivity.java | 16 - .../workers/temporal/stubs/TestWorkflow.java | 24 - .../temporal/stubs/ValidTestWorkflowImpl.java | 41 - .../TemporalActivityStubInterceptorTest.java | 142 - .../support/TemporalProxyHelperTest.java | 57 - .../sync/NormalizationActivityImplTest.java | 44 - .../sync/PersistStateActivityTest.java | 298 - .../temporal/sync/SyncWorkflowTest.java | 483 - .../sync/WebhookOperationActivityTest.java | 59 - .../io/airbyte/workers/tracing/DummySpan.java | 139 - .../StorageObjectGetInterceptorTest.java | 46 - .../tracing/TemporalSdkInterceptorTest.java | 143 - .../workers/utils/ConfigReplacerTest.java | 113 - .../src/test/resources/Dockerfile.no_var | 3 - .../src/test/resources/Dockerfile.with_var | 5 - ...te_discovered_postgres_catalog_output.json | 23 - .../resources/airbyte_postgres_catalog.json | 21 - .../test/resources/checkWorkflowHistory.json | 244 - .../connectionManagerWorkflowHistory.json | 2081 -- .../simple_postgres_catalog_output.json | 22 - ...mple_postgres_full_table_sync_catalog.json | 92 - .../test/resources/simple_postgres_init.sql | 33 - ...er_discovered_postgres_catalog_output.json | 22 - .../resources/singer_postgres_catalog.json | 90 - .../test/resources/stripe_schema_message.json | 862 - .../test/resources/syncWorkflowHistory.json | 718 - .../src/test/resources/valid_spec.json | 21 - build.gradle | 7 +- charts/airbyte-bootloader/.gitignore | 2 - charts/airbyte-bootloader/Chart.lock | 6 - charts/airbyte-bootloader/Chart.yaml | 32 - charts/airbyte-bootloader/README.md | 43 - .../airbyte-bootloader/templates/_helpers.tpl | 85 - .../templates/bootloader-secrets.yaml | 18 - charts/airbyte-bootloader/templates/pod.yaml | 122 - charts/airbyte-bootloader/values.yaml | 185 - .../.gitignore | 2 - .../Chart.lock | 6 - .../Chart.yaml | 31 - .../README.md | 79 - .../templates/_helpers.tpl | 73 - .../templates/deployment.yaml | 131 - .../templates/secrets.yaml | 17 - .../templates/service.yaml | 20 - .../values.yaml | 178 - charts/airbyte-cron/Chart.lock | 6 - charts/airbyte-cron/Chart.yaml | 31 - charts/airbyte-cron/README.md | 59 - charts/airbyte-cron/templates/_helpers.tpl | 73 - .../airbyte-cron/templates/cron-secrets.yaml | 18 - charts/airbyte-cron/templates/deployment.yaml | 148 - charts/airbyte-cron/values.yaml | 223 - charts/airbyte-metrics/.gitignore | 2 - charts/airbyte-metrics/.helmignore | 25 - charts/airbyte-metrics/Chart.lock | 6 - charts/airbyte-metrics/Chart.yaml | 32 - charts/airbyte-metrics/README.md | 43 - charts/airbyte-metrics/templates/_helpers.tpl | 53 - .../airbyte-metrics/templates/deployment.yaml | 135 - charts/airbyte-metrics/values.yaml | 102 - charts/airbyte-pod-sweeper/.gitignore | 2 - charts/airbyte-pod-sweeper/Chart.lock | 6 - charts/airbyte-pod-sweeper/Chart.yaml | 32 - charts/airbyte-pod-sweeper/README.md | 72 - .../templates/_helpers.tpl | 59 - .../templates/configmap.yaml | 52 - .../templates/deployment.yaml | 100 - charts/airbyte-pod-sweeper/values.yaml | 231 - charts/airbyte-server/.gitignore | 2 - charts/airbyte-server/Chart.lock | 6 - charts/airbyte-server/Chart.yaml | 31 - charts/airbyte-server/README.md | 79 - charts/airbyte-server/templates/_helpers.tpl | 73 - .../airbyte-server/templates/deployment.yaml | 317 - charts/airbyte-server/templates/secrets.yaml | 17 - charts/airbyte-server/templates/service.yaml | 23 - charts/airbyte-server/values.yaml | 415 - charts/airbyte-temporal/.gitignore | 2 - charts/airbyte-temporal/Chart.lock | 6 - charts/airbyte-temporal/Chart.yaml | 32 - charts/airbyte-temporal/README.md | 61 - .../airbyte-temporal/templates/_helpers.tpl | 59 - .../airbyte-temporal/templates/configmap.yaml | 50 - .../templates/deployment.yaml | 161 - .../airbyte-temporal/templates/secrets.yaml | 17 - .../airbyte-temporal/templates/service.yaml | 18 - charts/airbyte-temporal/values.yaml | 186 - charts/airbyte-webapp/.gitignore | 2 - charts/airbyte-webapp/Chart.lock | 6 - charts/airbyte-webapp/Chart.yaml | 32 - charts/airbyte-webapp/README.md | 68 - charts/airbyte-webapp/templates/_helpers.tpl | 74 - .../airbyte-webapp/templates/deployment.yaml | 166 - charts/airbyte-webapp/templates/ingress.yaml | 62 - charts/airbyte-webapp/templates/secrets.yaml | 17 - charts/airbyte-webapp/templates/service.yaml | 26 - charts/airbyte-webapp/values.yaml | 255 - charts/airbyte-worker/.gitignore | 2 - charts/airbyte-worker/Chart.lock | 6 - charts/airbyte-worker/Chart.yaml | 32 - charts/airbyte-worker/README.md | 80 - charts/airbyte-worker/templates/_helpers.tpl | 73 - .../airbyte-worker/templates/deployment.yaml | 459 - charts/airbyte-worker/templates/secrets.yaml | 17 - charts/airbyte-worker/values.yaml | 378 - charts/airbyte/.gitignore | 2 - charts/airbyte/.helmignore | 25 - charts/airbyte/Chart.lock | 33 - charts/airbyte/Chart.yaml | 67 - charts/airbyte/Chart.yaml.test | 71 - charts/airbyte/README.md | 275 - charts/airbyte/ci.sh | 91 - charts/airbyte/templates/NOTES.txt | 22 - charts/airbyte/templates/_helpers.tpl | 294 - charts/airbyte/templates/airbyte-db.yaml | 64 - charts/airbyte/templates/env-configmap.yaml | 75 - .../templates/gcs-log-creds-secret.yaml | 11 - charts/airbyte/templates/minio.yaml | 68 - charts/airbyte/templates/secret.yaml | 21 - charts/airbyte/templates/serviceaccount.yaml | 37 - .../airbyte/templates/tests/test-webapp.yaml | 16 - charts/airbyte/values.yaml | 1452 -- charts/airbyte/values.yaml.test | 1430 -- docker-compose-cloud.buildx.yaml | 134 - docker-compose.acceptance-test.yaml | 13 - docker-compose.build.yaml | 73 - docker-compose.datadog.yaml | 55 - docker-compose.debug.yaml | 39 - docker-compose.yaml | 289 - flags.yml | 5 - gradle.properties | 2 + settings.gradle | 23 +- temporal/dynamicconfig/development.yaml | 41 - terraform/README.md | 1 - terraform/aws/demo/core/init.sh | 41 - terraform/aws/demo/core/main.tf | 67 - terraform/aws/demo/core/outputs.tf | 3 - terraform/aws/demo/core/variables.tf | 19 - terraform/aws/demo/lb/auth.html | 21 - terraform/aws/demo/lb/main.tf | 180 - terraform/aws/demo/lb/variables.tf | 27 - terraform/aws/demo/main.tf | 28 - terraform/aws/demo/terraform.tf | 16 - terraform/aws/demo/variables.tf | 39 - tools/bin/check_images_exist.sh | 11 +- tools/bin/integration_tests_octavia.sh | 2 +- 2184 files changed, 14 insertions(+), 181186 deletions(-) delete mode 100644 .env delete mode 100644 .env.dev delete mode 100644 .github/actions/build-and-push-branch/action.yml delete mode 100644 .github/actions/build-branch/action.yml delete mode 100644 .github/workflows/publish-helm-charts.yml delete mode 100644 .github/workflows/publish-oss-for-cloud.yml delete mode 100644 .github/workflows/run-performance-test.yml delete mode 100644 airbyte-bootloader/Dockerfile delete mode 100644 airbyte-bootloader/Readme.md delete mode 100644 airbyte-bootloader/build.gradle delete mode 100644 airbyte-bootloader/gradle.properties delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/Application.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/Bootloader.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/DefaultPostLoadExecutor.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/ProtocolVersionChecker.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/SecretMigrator.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/ApplicationBeanFactory.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/DatabaseBeanFactory.java delete mode 100644 airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/SecretPersistenceBeanFactory.java delete mode 100644 airbyte-bootloader/src/main/resources/application.yml delete mode 100644 airbyte-bootloader/src/main/resources/banner/attention-banner.txt delete mode 100644 airbyte-bootloader/src/main/resources/micronaut-banner.txt delete mode 100644 airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderTest.java delete mode 100644 airbyte-bootloader/src/test/java/io/airbyte/bootloader/DefaultPostLoadExecutorTest.java delete mode 100644 airbyte-bootloader/src/test/java/io/airbyte/bootloader/ProtocolVersionCheckerTest.java delete mode 100644 airbyte-bootloader/src/test/java/io/airbyte/bootloader/SecretMigratorTest.java delete mode 100644 airbyte-commons-server/build.gradle delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/RequestLogger.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/ServerConstants.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ApiPojoConverters.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/CatalogDiffConverters.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ConfigurationUpdate.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/JobConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/NotificationConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OauthModelConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OperationsConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/SpecFetcher.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkflowStateConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkspaceWebhookConfigsConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ApplicationErrorKnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/BadObjectSchemaKnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ConnectFailureKnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundKnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InternalServerKnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidInputExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonInputExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/NotFoundExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UncaughtExceptionMapper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UnsupportedProtocolVersionException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ValueConflictKnownException.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/AttemptHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectionsHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/HealthCheckHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/JobHistoryHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/LogsHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OpenApiConfigHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OperationsHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SchedulerHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/StateHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WorkspacesHandler.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/CatalogConverter.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionMatcher.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionScheduleHelper.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/DestinationMatcher.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/Matchable.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/OAuthPathExtractor.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/SourceMatcher.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClient.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/EventRunner.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousJobMetadata.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousResponse.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousSchedulerClient.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/TemporalEventRunner.java delete mode 100644 airbyte-commons-server/src/main/java/io/airbyte/commons/server/services/AirbyteGithubStore.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/RequestLoggerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogConverterTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogDiffConvertersTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/ConfigurationUpdateTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/JobConverterTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/OauthModelConverterTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/AttemptHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionSchedulerHelperTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionsHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/HealthCheckHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/JobHistoryHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/LogsHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OAuthHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OpenApiConfigHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OperationsHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SchedulerHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SourceHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/StateHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WorkspacesHandlerTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/helper/OAuthPathExtractorTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectionHelpers.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectorSpecificationHelpers.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationDefinitionHelpers.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationHelpers.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceDefinitionHelpers.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceHelpers.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClientTest.java delete mode 100644 airbyte-commons-server/src/test/java/io/airbyte/commons/server/services/AirbyteGithubStoreTest.java delete mode 100644 airbyte-commons-server/src/test/resources/icons/test-destination.svg delete mode 100644 airbyte-commons-server/src/test/resources/icons/test-source.svg delete mode 100644 airbyte-commons-server/src/test/resources/json/TestImplementation.json delete mode 100644 airbyte-commons-server/src/test/resources/json/TestSpecification.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/03a4c904-c91d-447f-ab59-27a43b52c2fd.gz delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/4e00862d-5484-4f50-9860-f3bbb4317397.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/5434615d-a3b7-4351-bc6b-a9a695555a30.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/28ffee2b-372a-4f72-9b95-8ed56a8b99c5.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/e48cae1a-1f5c-42cc-9ec1-a44ff7fb4969.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/22f6c74f-5699-40ff-833c-4a879ea40133.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/25c5221d-dce2-4163-ade9-739ef790f503.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/424892c4-daac-4491-b35d-c6688ba547ba.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/8be1cf83-fde1-477f-a4ad-318d23c9f3c6.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/a625d593-bba5-4a1c-a53d-2d246268a816.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/af7c921e-5892-4ff2-b6c1-4a5ab258fb7e.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/f7a7d195-377f-cf5b-70a5-be6b819019dc.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2470e835-feaf-4db6-96f3-70fd645acc77.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2af123bf-0aaf-4e0d-9784-cb497f23741a.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/396e4ca3-8a97-4b85-aa4e-c9d8c2d5f992.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/41375467-61ae-4204-8e38-e2b8b7365f23.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/435bb9a5-7887-4809-aa58-28c27df0d7ad.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/445831eb-78db-4b1f-8f1f-0d96ad8739e2.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/4eb22946-2a79-4d20-a3e6-effd234613c3.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/57eb1576-8f52-463d-beb6-2e107cdf571d.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/59f1e50a-331f-4f09-b3e8-2e8d4d355f44.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/68e63de2-bb83-4c7e-93fa-a8a9051e3993.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/71607ba1-c0ac-4799-8049-7f4b90dd50f7.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/778daa7c-feaf-4db6-96f3-70fd645acc77.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/859e501d-2b67-471f-91bb-1c801414d28f.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9e0556f4-69df-4522-a3fb-03264d36b348.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9fed261d-d107-47fd-8c8b-323023db6e20.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/aea2fd0d-377d-465e-86c0-4fdc4f688e51.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b03a9f3e-22a5-11eb-adc1-0242ac120002.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b1892b11-788d-44bd-b9ec-3a436f7b54ce.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b5ea17b1-f170-46dc-bc31-cc744ca984c1.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/cd42861b-01fc-4658-a8ab-5d11d0510f01.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d2147be5-fa36-4936-977e-f031affa5895.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d29764f8-80d7-4dd7-acbe-1a42005ee5aa.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d8313939-3782-41b0-be29-b3ca20d8dd3a.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/decd338e-5647-4c0b-adf4-da0e75f5a750.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e094cb9a-26de-4645-8761-65c0c425d1de.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e7778cfc-e97c-4458-9ecb-b4f2bba8946c.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e87ffa8e-a3b5-f69c-9076-6011339de1f6.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/eaf50f04-21dd-4620-913b-2a83f5635227.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ec4b9503-13cb-48ab-a4ab-6ade4be46567.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ed799e2b-2158-4c66-8da4-b40fe63bc72a.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ef69ef6e-aa7f-4af1-a01d-ef775033524e.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/a294256f-1abe-4837-925f-91602c7207b4.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/a294256f-1abe-4837-925f-91602c7207b4.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_WORKSPACE/5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6.json delete mode 100644 airbyte-commons-server/src/test/resources/migration/schema.sql delete mode 100644 airbyte-connector-builder-server/.coveragerc delete mode 100644 airbyte-connector-builder-server/.dockerignore delete mode 100644 airbyte-connector-builder-server/.gitignore delete mode 100644 airbyte-connector-builder-server/.python-version delete mode 100644 airbyte-connector-builder-server/CDK_VERSION delete mode 100644 airbyte-connector-builder-server/CHANGELOG.md delete mode 100644 airbyte-connector-builder-server/Dockerfile delete mode 100644 airbyte-connector-builder-server/README.md delete mode 100644 airbyte-connector-builder-server/build.gradle delete mode 100644 airbyte-connector-builder-server/connector_builder/__init__.py delete mode 100644 airbyte-connector-builder-server/connector_builder/entrypoint.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/apis/__init__.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/apis/default_api_interface.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/__init__.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/add_fields.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/add_fields_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/added_field_definition.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/check_stream.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/config_component_schema.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/connector_manifest.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/declarative_stream.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/default_paginator.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/default_paginator_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/extra_models.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/http_request.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/http_requester.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/http_requester_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/http_response.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/http_response_filter.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/interpolated_boolean.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/interpolated_string.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_exception_info.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_property.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/json_decoder.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/known_exception_info.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/min_max_datetime.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/no_auth.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/no_pagination.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/offset_increment.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/offset_increment_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/page_increment.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/page_increment_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/paginator.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/parent_stream_config.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/parsed_add_field_definition.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/record_filter.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/record_selector.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/record_selector_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/remove_fields.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/remove_fields_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/request_option.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/requester.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest_request_body.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/single_slice.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/stream_read.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/stream_read_pages.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/stream_read_request_body.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slice_descriptor.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slices.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/stream_slicer.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read_streams.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/streams_list_request_body.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy.py delete mode 100644 airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy_all_of.py delete mode 100644 airbyte-connector-builder-server/connector_builder/impl/adapter.py delete mode 100644 airbyte-connector-builder-server/connector_builder/impl/default_api.py delete mode 100644 airbyte-connector-builder-server/connector_builder/impl/low_code_cdk_adapter.py delete mode 100644 airbyte-connector-builder-server/dist/connector_builder_server-0.40.21-py3.10.egg delete mode 100644 airbyte-connector-builder-server/gradle.properties delete mode 100644 airbyte-connector-builder-server/integration_tests/test_integration_test.py delete mode 100644 airbyte-connector-builder-server/openapi/README.md delete mode 100644 airbyte-connector-builder-server/openapi/generator_config.yaml delete mode 100644 airbyte-connector-builder-server/openapi/templates/api_interfaces.mustache delete mode 100644 airbyte-connector-builder-server/pytest.ini delete mode 100755 airbyte-connector-builder-server/run_format.sh delete mode 100755 airbyte-connector-builder-server/run_tests.sh delete mode 100644 airbyte-connector-builder-server/setup.py delete mode 100644 airbyte-connector-builder-server/src/main/openapi/openapi.yaml delete mode 100644 airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_default_api.py delete mode 100644 airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_low_code_cdk_adapter.py delete mode 100644 airbyte-connector-builder-server/unit_tests/test_unit_test.py delete mode 100644 airbyte-container-orchestrator/Dockerfile delete mode 100644 airbyte-container-orchestrator/build.gradle delete mode 100644 airbyte-container-orchestrator/gradle.properties delete mode 100644 airbyte-container-orchestrator/readme.md delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/Application.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/AsyncStateManager.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/EventListeners.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/HeartbeatController.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ConfigFactory.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactory.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/DbtJobOrchestrator.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/JobOrchestrator.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NoOpOrchestrator.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NormalizationJobOrchestrator.java delete mode 100644 airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/ReplicationJobOrchestrator.java delete mode 100644 airbyte-container-orchestrator/src/main/resources/application.yml delete mode 100644 airbyte-container-orchestrator/src/main/resources/micronaut-banner.txt delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/ApplicationTest.java delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/AsyncStateManagerTest.java delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/EventListenersTest.java delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/HeartbeatControllerTest.java delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ConfigFactoryTest.java delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryK8sTest.java delete mode 100644 airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryTest.java delete mode 100644 airbyte-container-orchestrator/src/test/resources/application.yml delete mode 100644 airbyte-container-orchestrator/src/test/resources/files/KUBE_POD_INFO delete mode 100644 airbyte-container-orchestrator/src/test/resources/files/application.txt delete mode 100644 airbyte-container-orchestrator/src/test/resources/files/destinationLauncherConfig.json delete mode 100644 airbyte-container-orchestrator/src/test/resources/files/envMap.json delete mode 100644 airbyte-container-orchestrator/src/test/resources/files/input.json delete mode 100644 airbyte-container-orchestrator/src/test/resources/files/jobRunConfig.json delete mode 100644 airbyte-cron/Dockerfile delete mode 100644 airbyte-cron/LICENSE delete mode 100644 airbyte-cron/build.gradle delete mode 100644 airbyte-cron/gradle.properties delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/ApplicationInitializer.java delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/MicronautCronRunner.java delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/config/ApplicationBeanFactory.java delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/config/DatabaseBeanFactory.java delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/DefinitionsUpdater.java delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/Temporal.java delete mode 100644 airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/WorkspaceCleaner.java delete mode 100644 airbyte-cron/src/main/resources/application.yml delete mode 100644 airbyte-cron/src/main/resources/micronaut-banner.txt delete mode 100644 airbyte-metrics/reporter/Dockerfile delete mode 100644 airbyte-metrics/reporter/README.md delete mode 100644 airbyte-metrics/reporter/build.gradle delete mode 100644 airbyte-metrics/reporter/gradle.properties delete mode 100644 airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Application.java delete mode 100644 airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Emitter.java delete mode 100644 airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/EventListeners.java delete mode 100644 airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/MetricRepository.java delete mode 100644 airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/ReporterFactory.java delete mode 100644 airbyte-metrics/reporter/src/main/resources/application.yml delete mode 100644 airbyte-metrics/reporter/src/main/resources/micronaut-banner.txt delete mode 100644 airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/EmitterTest.java delete mode 100644 airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/MetricRepositoryTest.java delete mode 100644 airbyte-proxy/401.html delete mode 100644 airbyte-proxy/Dockerfile delete mode 100644 airbyte-proxy/LICENSE delete mode 100644 airbyte-proxy/README.md delete mode 100644 airbyte-proxy/build.gradle delete mode 100644 airbyte-proxy/gradle.properties delete mode 100644 airbyte-proxy/nginx-auth.conf.template delete mode 100644 airbyte-proxy/nginx-no-auth.conf.template delete mode 100644 airbyte-proxy/run.sh delete mode 100755 airbyte-proxy/test.sh delete mode 100644 airbyte-server/.gitignore delete mode 100644 airbyte-server/Dockerfile delete mode 100644 airbyte-server/build.gradle delete mode 100644 airbyte-server/gradle.properties delete mode 100644 airbyte-server/readme.md delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/Application.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/CorsFilter.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/DatabaseEventListener.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/ServerApp.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/ServerFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/ServerRunnable.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/ApiHelper.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/AttemptApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/ConnectionApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/DestinationApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionSpecificationApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/DestinationOauthApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/HealthApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/JobsApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/LogsApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/NotFoundController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/NotificationsApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/OpenapiApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/OperationApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/SchedulerApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/SourceApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionSpecificationApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/SourceOauthApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/StateApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/WebBackendApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/apis/WorkspaceApiController.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/ApplicationBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/CloudStorageBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/DatabaseBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/HelperBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/JobErrorReportingBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/SecretPersistenceBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/config/TemporalBeanFactory.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/errors/InvalidInputExceptionHandler.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonExceptionHandler.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonInputExceptionHandler.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/errors/KnownExceptionHandler.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/errors/NotFoundExceptionHandler.java delete mode 100644 airbyte-server/src/main/java/io/airbyte/server/errors/UncaughtExceptionHandler.java delete mode 100644 airbyte-server/src/main/resources/application.yml delete mode 100644 airbyte-server/src/main/resources/micronaut-banner.txt delete mode 100644 airbyte-server/src/test/java/io/airbyte/server/apis/HealthCheckApiTest.java delete mode 100644 airbyte-temporal/.gitignore delete mode 100644 airbyte-temporal/Dockerfile delete mode 100644 airbyte-temporal/README.md delete mode 100644 airbyte-temporal/build.gradle delete mode 100644 airbyte-temporal/gradle.properties delete mode 100755 airbyte-temporal/scripts/build-temporal.sh delete mode 100755 airbyte-temporal/scripts/update-and-start-temporal.sh delete mode 100644 airbyte-tests/build.gradle delete mode 100644 airbyte-tests/readme.md delete mode 100644 airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/AdvancedAcceptanceTests.java delete mode 100644 airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/BasicAcceptanceTests.java delete mode 100644 airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/CdcAcceptanceTests.java delete mode 100644 airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/ContainerOrchestratorAcceptanceTests.java delete mode 100644 airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/VersioningAcceptanceTests.java delete mode 100644 airbyte-tests/src/acceptanceTests/resources/postgres_init.sql delete mode 100644 airbyte-tests/src/acceptanceTests/resources/postgres_init_cdc.sql delete mode 100644 airbyte-tests/src/acceptanceTests/resources/postgres_second_schema_multiple_tables.sql delete mode 100644 airbyte-tests/src/acceptanceTests/resources/postgres_separate_schema_same_table.sql delete mode 100644 airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/ImportApi.java delete mode 100644 airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/MigrationAcceptanceTest.java delete mode 100644 airbyte-tests/src/automaticMigrationAcceptanceTest/resources/03a4c904-c91d-447f-ab59-27a43b52c2fd.gz delete mode 100644 airbyte-tests/src/automaticMigrationAcceptanceTest/resources/docker-compose-migration-test-0-32-0-alpha.yaml delete mode 100644 airbyte-tests/src/automaticMigrationAcceptanceTest/resources/env-file-migration-test-0-32-0.env delete mode 100644 airbyte-webapp-e2e-tests/.eslintrc.js delete mode 100644 airbyte-webapp-e2e-tests/.gitignore delete mode 100644 airbyte-webapp-e2e-tests/.npmrc delete mode 100644 airbyte-webapp-e2e-tests/.nvmrc delete mode 120000 airbyte-webapp-e2e-tests/.prettierrc.js delete mode 100644 airbyte-webapp-e2e-tests/README.md delete mode 100644 airbyte-webapp-e2e-tests/build.gradle delete mode 100644 airbyte-webapp-e2e-tests/cypress.json delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/api.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/index.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/types.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/common.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/connection.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/connector.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/connectorBuilder.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/db/db.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/db/index.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/destination.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/interceptors.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/source.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/global.d.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/base.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/connection/streamTable.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/connectorBuilder.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/onboarding.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/connectorBuilderPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/createConnectorPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/destinationPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/newConnectionPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/settingsConnectionPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/sidebar.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/sourcePage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/plugins/index.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/support/index.js delete mode 100644 airbyte-webapp-e2e-tests/dummy_api.js delete mode 100644 airbyte-webapp-e2e-tests/package-lock.json delete mode 100644 airbyte-webapp-e2e-tests/package.json delete mode 100644 airbyte-webapp-e2e-tests/tsconfig.json delete mode 100644 airbyte-webapp/.env delete mode 100644 airbyte-webapp/.eslintrc.js delete mode 100644 airbyte-webapp/.gitattributes delete mode 100644 airbyte-webapp/.gitignore delete mode 100755 airbyte-webapp/.husky/pre-commit delete mode 100644 airbyte-webapp/.npmrc delete mode 100644 airbyte-webapp/.nvmrc delete mode 100644 airbyte-webapp/.prettierrc.js delete mode 100644 airbyte-webapp/.storybook/logo.png delete mode 100644 airbyte-webapp/.storybook/main.ts delete mode 100644 airbyte-webapp/.storybook/manager.ts delete mode 100644 airbyte-webapp/.storybook/preview.ts delete mode 100644 airbyte-webapp/.storybook/theme.tsx delete mode 100644 airbyte-webapp/.storybook/withProvider.tsx delete mode 100644 airbyte-webapp/.stylelintignore delete mode 100644 airbyte-webapp/.stylelintrc delete mode 100644 airbyte-webapp/Dockerfile delete mode 100644 airbyte-webapp/README.md delete mode 100644 airbyte-webapp/STYLEGUIDE.md delete mode 100644 airbyte-webapp/babel.config.js delete mode 100644 airbyte-webapp/build.gradle delete mode 100644 airbyte-webapp/docs/HowTo-ConnectionSpecification.md delete mode 100644 airbyte-webapp/docs/HowTo-EnvVariables.md delete mode 100644 airbyte-webapp/docs/img.png delete mode 100644 airbyte-webapp/gradle.properties delete mode 100644 airbyte-webapp/index.html delete mode 100644 airbyte-webapp/jest.config.ts delete mode 100644 airbyte-webapp/nginx/default.conf.template delete mode 100644 airbyte-webapp/orval.config.ts delete mode 100644 airbyte-webapp/package.json delete mode 100644 airbyte-webapp/packages/README.md delete mode 100644 airbyte-webapp/packages/eslint-plugin/index.js delete mode 100644 airbyte-webapp/packages/eslint-plugin/no-hardcoded-connector-ids.js delete mode 100644 airbyte-webapp/packages/stylelint-plugin/index.js delete mode 100644 airbyte-webapp/packages/stylelint-plugin/no-color-variables-in-rgba.js delete mode 100644 airbyte-webapp/packages/stylelint-plugin/no-use-renaming.js delete mode 100644 airbyte-webapp/packages/vite-plugins/build-info.ts delete mode 100644 airbyte-webapp/packages/vite-plugins/doc-middleware.ts delete mode 100644 airbyte-webapp/packages/vite-plugins/index.ts delete mode 100644 airbyte-webapp/patches/react-virtualized@9.22.3.patch delete mode 100644 airbyte-webapp/pnpm-lock.yaml delete mode 100644 airbyte-webapp/public/cactus.png delete mode 100644 airbyte-webapp/public/cloud-main-logo.svg delete mode 100644 airbyte-webapp/public/connectors/google/btn_google_light_normal_ios.svg delete mode 100644 airbyte-webapp/public/default-logo-catalog.svg delete mode 100644 airbyte-webapp/public/empty-connections.png delete mode 100644 airbyte-webapp/public/empty-destinations.png delete mode 100644 airbyte-webapp/public/empty-sources.png delete mode 100644 airbyte-webapp/public/favicon.ico delete mode 100644 airbyte-webapp/public/fonts/inter/Inter-italic.var.woff2 delete mode 100644 airbyte-webapp/public/fonts/inter/Inter-roman.var.woff2 delete mode 100644 airbyte-webapp/public/fonts/roboto/Roboto-Medium.eot delete mode 100644 airbyte-webapp/public/fonts/roboto/Roboto-Medium.svg delete mode 100644 airbyte-webapp/public/fonts/roboto/Roboto-Medium.ttf delete mode 100644 airbyte-webapp/public/fonts/roboto/Roboto-Medium.woff delete mode 100644 airbyte-webapp/public/fonts/roboto/Roboto-Medium.woff2 delete mode 100644 airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.eot delete mode 100644 airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.svg delete mode 100644 airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.ttf delete mode 100644 airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.woff delete mode 100644 airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.woff2 delete mode 100644 airbyte-webapp/public/images/airbyte/logo.svg delete mode 100644 airbyte-webapp/public/images/connector-builder/import-yaml.svg delete mode 100644 airbyte-webapp/public/images/connector-builder/load-existing-connector.svg delete mode 100644 airbyte-webapp/public/images/connector-builder/start-from-scratch.svg delete mode 100644 airbyte-webapp/public/images/octavia/biting-nails.png delete mode 100644 airbyte-webapp/public/images/octavia/pointing.svg delete mode 100644 airbyte-webapp/public/images/testimonials/cartdotcom-logo.svg delete mode 100644 airbyte-webapp/public/images/testimonials/cartdotcom-person-photo.png delete mode 100644 airbyte-webapp/public/index.css delete mode 100644 airbyte-webapp/public/logo.png delete mode 100644 airbyte-webapp/public/logo112.png delete mode 100644 airbyte-webapp/public/logo224.png delete mode 100644 airbyte-webapp/public/logo336.png delete mode 100644 airbyte-webapp/public/manifest.json delete mode 100644 airbyte-webapp/public/newsletter.png delete mode 100644 airbyte-webapp/public/play.svg delete mode 100644 airbyte-webapp/public/process-arrow.svg delete mode 100644 airbyte-webapp/public/rectangle.svg delete mode 100644 airbyte-webapp/public/robots.txt delete mode 100644 airbyte-webapp/public/rocket.png delete mode 100644 airbyte-webapp/public/videoCover.png delete mode 100644 airbyte-webapp/public/welcome.svg delete mode 100644 airbyte-webapp/scripts/dev-overwrites.js delete mode 100644 airbyte-webapp/scripts/environment.js delete mode 100644 airbyte-webapp/scripts/license-check.js delete mode 100755 airbyte-webapp/scripts/load-declarative-schema.sh delete mode 100644 airbyte-webapp/scripts/validate-links.ts delete mode 100644 airbyte-webapp/src/App.tsx delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/ArrayOfObjectsEditor.module.scss delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/ArrayOfObjectsEditor.tsx delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/components/EditorHeader.module.scss delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/components/EditorHeader.test.tsx delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/components/EditorHeader.tsx delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/components/EditorRow.module.scss delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/components/EditorRow.tsx delete mode 100644 airbyte-webapp/src/components/ArrayOfObjectsEditor/index.tsx delete mode 100644 airbyte-webapp/src/components/CloudInviteUsersHint/CloudInviteUsersHint.tsx delete mode 100644 airbyte-webapp/src/components/CloudInviteUsersHint/index.ts delete mode 100644 airbyte-webapp/src/components/ConnectorBlocks/FormPageContent.module.scss delete mode 100644 airbyte-webapp/src/components/ConnectorBlocks/FormPageContent.tsx delete mode 100644 airbyte-webapp/src/components/ConnectorBlocks/ItemTabs.tsx delete mode 100644 airbyte-webapp/src/components/ConnectorBlocks/TableItemTitle.module.scss delete mode 100644 airbyte-webapp/src/components/ConnectorBlocks/TableItemTitle.tsx delete mode 100644 airbyte-webapp/src/components/ConnectorBlocks/index.tsx delete mode 100644 airbyte-webapp/src/components/ConnectorCard/ConnectorCard.module.scss delete mode 100644 airbyte-webapp/src/components/ConnectorCard/ConnectorCard.tsx delete mode 100644 airbyte-webapp/src/components/ConnectorCard/index.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/ConnectionTable.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/ConnectionTable.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/ImplementationTable.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/ImplementationTable.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/AllConnectionsStatusCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ChangesStatusIcon.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ChangesStatusIcon.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ConnectEntitiesCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ConnectionSettingsCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ConnectionStatusCell.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ConnectionStatusCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ConnectorNameCell.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/ConnectorNameCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/EntityNameCell.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/EntityNameCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/FrequencyCell.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/FrequencyCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/LastSyncCell.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/LastSyncCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/StatusCell.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/StatusCell.test.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/components/StatusCellControl.module.scss delete mode 100644 airbyte-webapp/src/components/EntityTable/components/StatusCellControl.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/index.tsx delete mode 100644 airbyte-webapp/src/components/EntityTable/types.ts delete mode 100644 airbyte-webapp/src/components/EntityTable/utils.tsx delete mode 100644 airbyte-webapp/src/components/GroupControls/GroupControls.module.scss delete mode 100644 airbyte-webapp/src/components/GroupControls/GroupControls.tsx delete mode 100644 airbyte-webapp/src/components/GroupControls/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/GroupControls/index.tsx delete mode 100644 airbyte-webapp/src/components/Indicator/Indicator.module.scss delete mode 100644 airbyte-webapp/src/components/Indicator/Indicator.tsx delete mode 100644 airbyte-webapp/src/components/Indicator/index.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/JobItem.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/JobItem.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/attemptLinkUtils.ts delete mode 100644 airbyte-webapp/src/components/JobItem/components/AttemptDetails.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/components/AttemptDetails.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/ContentWrapper.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/components/ContentWrapper.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/DebugInfoDetailsModal.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/components/DownloadButton.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/ErrorDetails.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/JobLogs.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/components/JobLogs.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/LinkToAttemptButton.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/Logs.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/LogsDetails.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/MainInfo.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/components/MainInfo.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/ResetStreamDetails.module.scss delete mode 100644 airbyte-webapp/src/components/JobItem/components/ResetStreamDetails.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/components/Tabs.tsx delete mode 100644 airbyte-webapp/src/components/JobItem/index.ts delete mode 100644 airbyte-webapp/src/components/JobItem/types.ts delete mode 100644 airbyte-webapp/src/components/JobItem/utils.ts delete mode 100644 airbyte-webapp/src/components/Label/Label.tsx delete mode 100644 airbyte-webapp/src/components/Label/index.tsx delete mode 100644 airbyte-webapp/src/components/LabeledControl/ControlLabels.module.scss delete mode 100644 airbyte-webapp/src/components/LabeledControl/ControlLabels.tsx delete mode 100644 airbyte-webapp/src/components/LabeledControl/index.tsx delete mode 100644 airbyte-webapp/src/components/LabeledInput/LabeledInput.tsx delete mode 100644 airbyte-webapp/src/components/LabeledInput/index.tsx delete mode 100644 airbyte-webapp/src/components/LabeledRadioButton/LabeledRadioButton.tsx delete mode 100644 airbyte-webapp/src/components/LabeledRadioButton/index.tsx delete mode 100644 airbyte-webapp/src/components/LabeledSwitch/LabeledSwitch.module.scss delete mode 100644 airbyte-webapp/src/components/LabeledSwitch/LabeledSwitch.tsx delete mode 100644 airbyte-webapp/src/components/LabeledSwitch/index.tsx delete mode 100644 airbyte-webapp/src/components/LoadingPage/LoadingPage.tsx delete mode 100644 airbyte-webapp/src/components/LoadingPage/index.tsx delete mode 100644 airbyte-webapp/src/components/LoadingSchema/LoadingSchema.tsx delete mode 100644 airbyte-webapp/src/components/LoadingSchema/index.tsx delete mode 100644 airbyte-webapp/src/components/Placeholder/Placeholder.tsx delete mode 100644 airbyte-webapp/src/components/Placeholder/index.tsx delete mode 100644 airbyte-webapp/src/components/Placeholder/types.ts delete mode 100644 airbyte-webapp/src/components/ReleaseStageBadge/ReleaseStageBadge.module.scss delete mode 100644 airbyte-webapp/src/components/ReleaseStageBadge/ReleaseStageBadge.tsx delete mode 100644 airbyte-webapp/src/components/ReleaseStageBadge/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ReleaseStageBadge/index.ts delete mode 100644 airbyte-webapp/src/components/SimpleTableComponents/SimpleTableComponents.tsx delete mode 100644 airbyte-webapp/src/components/SimpleTableComponents/index.tsx delete mode 100644 airbyte-webapp/src/components/base/Titles/Titles.tsx delete mode 100644 airbyte-webapp/src/components/base/Titles/index.tsx delete mode 100644 airbyte-webapp/src/components/common/ApiErrorBoundary/ApiErrorBoundary.tsx delete mode 100644 airbyte-webapp/src/components/common/ApiErrorBoundary/ServerUnavailableView.tsx delete mode 100644 airbyte-webapp/src/components/common/ApiErrorBoundary/index.ts delete mode 100644 airbyte-webapp/src/components/common/ConfirmationModal/ConfirmationModal.module.scss delete mode 100644 airbyte-webapp/src/components/common/ConfirmationModal/ConfirmationModal.tsx delete mode 100644 airbyte-webapp/src/components/common/ConfirmationModal/index.ts delete mode 100644 airbyte-webapp/src/components/common/ConnectorIcon/ConnectorIcon.module.scss delete mode 100644 airbyte-webapp/src/components/common/ConnectorIcon/ConnectorIcon.story.module.scss delete mode 100644 airbyte-webapp/src/components/common/ConnectorIcon/ConnectorIcon.tsx delete mode 100644 airbyte-webapp/src/components/common/ConnectorIcon/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/common/ConnectorIcon/index.ts delete mode 100644 airbyte-webapp/src/components/common/DataGeographyDropdown/DataGeographyDropdown.module.scss delete mode 100644 airbyte-webapp/src/components/common/DataGeographyDropdown/DataGeographyDropdown.tsx delete mode 100644 airbyte-webapp/src/components/common/DataGeographyDropdown/index.ts delete mode 100644 airbyte-webapp/src/components/common/DefaultLogoCatalog/DefaultLogoCatalog.tsx delete mode 100644 airbyte-webapp/src/components/common/DefaultLogoCatalog/index.ts delete mode 100644 airbyte-webapp/src/components/common/DeleteBlock/DeleteBlock.module.scss delete mode 100644 airbyte-webapp/src/components/common/DeleteBlock/DeleteBlock.tsx delete mode 100644 airbyte-webapp/src/components/common/DeleteBlock/index.ts delete mode 100644 airbyte-webapp/src/components/common/EmptyResourceBlock/EmptyResourceBlock.module.scss delete mode 100644 airbyte-webapp/src/components/common/EmptyResourceBlock/EmptyResourceBlock.tsx delete mode 100644 airbyte-webapp/src/components/common/EmptyResourceBlock/index.ts delete mode 100644 airbyte-webapp/src/components/common/FormChangeTracker/FormChangeTracker.tsx delete mode 100644 airbyte-webapp/src/components/common/FormChangeTracker/index.ts delete mode 100644 airbyte-webapp/src/components/common/HeadTitle/HeadTitle.tsx delete mode 100644 airbyte-webapp/src/components/common/HeadTitle/index.ts delete mode 100644 airbyte-webapp/src/components/common/Link/Link.tsx delete mode 100644 airbyte-webapp/src/components/common/Link/index.ts delete mode 100644 airbyte-webapp/src/components/common/MainPageWithScroll/MainPageWithScroll.module.scss delete mode 100644 airbyte-webapp/src/components/common/MainPageWithScroll/MainPageWithScroll.tsx delete mode 100644 airbyte-webapp/src/components/common/MainPageWithScroll/index.ts delete mode 100644 airbyte-webapp/src/components/common/PageViewContainer/BaseClearView.module.scss delete mode 100644 airbyte-webapp/src/components/common/PageViewContainer/BaseClearView.tsx delete mode 100644 airbyte-webapp/src/components/common/PageViewContainer/PaddedCard.tsx delete mode 100644 airbyte-webapp/src/components/common/PageViewContainer/PageViewContainer.tsx delete mode 100644 airbyte-webapp/src/components/common/PageViewContainer/index.ts delete mode 100644 airbyte-webapp/src/components/common/Version/Version.tsx delete mode 100644 airbyte-webapp/src/components/common/Version/index.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/CatalogDiffModal.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/CatalogDiffModal.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/CatalogDiffModal.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffAccordion.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffAccordion.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffAccordionHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffAccordionHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffFieldTable.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffFieldTable.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffIconBlock.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffIconBlock.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffSection.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/DiffSection.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/FieldRow.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/FieldRow.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/FieldSection.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/FieldSection.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/StreamRow.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/StreamRow.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/index.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/types.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogDiffModal/utils.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/Arrow.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/Arrow.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/BulkHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/BulkHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogSection.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogSection.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTree.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTree.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeBody.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeBody.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeSearch.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeSearch.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeSubheader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/CatalogTreeSubheader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/DataTypeCell.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/FieldHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/FieldRow.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/PathPopout.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/PathPopout.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/PathPopoutButton.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/PathPopoutButton.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/StreamFieldTable.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/StreamFieldTable.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/StreamHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/StreamHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/SyncSettingsDropdown.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/TreeRowWrapper.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/TreeRowWrapper.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/index.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/BulkEditPanel.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/BulkEditPanel.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/BulkEditPanel.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableCell.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableCell.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableRow.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableRow.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableRowIcon.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/CatalogTreeTableRowIcon.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamConnectionHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamConnectionHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamDetailsPanel.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamDetailsPanel.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/ConnectorHeaderGroupIcon.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/ConnectorHeaderGroupIcon.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/CursorCell/CursorCell.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/CursorCell/CursorCell.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/CursorCell/index.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/PKCell/PKCell.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/PKCell/index.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/SyncFieldCell/SyncFieldCell.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/SyncFieldCell/index.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamPanelHeader/StreamPanelHeader.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamPanelHeader/StreamPanelHeader.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamPathSelect.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/StreamPathSelect.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/SyncModeSelect.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/SyncModeSelect.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/__snapshots__/BulkEditPanel.test.tsx.snap delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/useCatalogTreeTableRowProps.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/next/useCatalogTreeTableRowProps.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/streamConfigHelpers/index.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/streamConfigHelpers/streamConfigHelpers.test.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/streamConfigHelpers/streamConfigHelpers.ts delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/styles.tsx delete mode 100644 airbyte-webapp/src/components/connection/CatalogTree/utils.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionBlock/ConnectionBlock.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionBlock/ConnectionBlock.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionBlock/ConnectionBlockItem.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionBlock/index.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionEditFormCard/ConnectionEditFormCard.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionEditFormCard/ConnectionEditFormCard.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionEditFormCard/index.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ConnectionForm.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ConnectionFormFields.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ConnectionFormFields.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/CreateControls.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/CreateControls.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/EditControls.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/EditControls.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/NamespaceDefinitionField.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/NamespaceDefinitionField.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/NonBreakingChangesPreferenceField.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/NonBreakingChangesPreferenceField.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/NormalizationField.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/NormalizationField.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/OctaviaRedFlag.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/OctaviaYellowFlag.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/OperationsSection.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ResponseMessage.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ResponseMessage.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ScheduleField.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/ScheduleField.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/SchemaChangeBackdrop.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/SchemaChangeBackdrop.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/SchemaChangesBackdrop.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/Section.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/Section.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/SyncCatalogField.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/SyncCatalogField.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/TransformationField.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/__snapshots__/SchemaChangesBackdrop.test.tsx.snap delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/__snapshots__/formConfig.test.ts.snap delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/calculateInitialCatalog.test.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/calculateInitialCatalog.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/formConfig.test.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/formConfig.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionForm/refreshSourceSchemaWithConfirmationOnDirty.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/ConnectionInfoCard.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/ConnectionInfoCard.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/ConnectionInfoCard.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/EnabledControl.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/EnabledControl.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionInfoCard/index.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionName/ConnectionName.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionName/ConnectionName.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionName/index.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionOnboarding/AirbyteIllustration.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionOnboarding/AirbyteIllustration.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionOnboarding/ConnectionOnboarding.module.scss delete mode 100644 airbyte-webapp/src/components/connection/ConnectionOnboarding/ConnectionOnboarding.tsx delete mode 100644 airbyte-webapp/src/components/connection/ConnectionOnboarding/index.ts delete mode 100644 airbyte-webapp/src/components/connection/ConnectionOnboarding/plusIcon.svg delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/CreateConnectionForm.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/CreateConnectionForm.test.tsx delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/CreateConnectionForm.tsx delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/CreateConnectionNameField.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/CreateConnectionNameField.tsx delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/DataResidency.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/DataResidency.tsx delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/SchemaError.tsx delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/TryAfterErrorBlock.module.scss delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/TryAfterErrorBlock.tsx delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/__snapshots__/CreateConnectionForm.test.tsx.snap delete mode 100644 airbyte-webapp/src/components/connection/CreateConnectionForm/index.tsx delete mode 100644 airbyte-webapp/src/components/connection/DestinationNamespaceModal/DestinationNamespaceModal.module.scss delete mode 100644 airbyte-webapp/src/components/connection/DestinationNamespaceModal/DestinationNamespaceModal.tsx delete mode 100644 airbyte-webapp/src/components/connection/DestinationNamespaceModal/ExampleSettingsTable.module.scss delete mode 100644 airbyte-webapp/src/components/connection/DestinationNamespaceModal/ExampleSettingsTable.tsx delete mode 100644 airbyte-webapp/src/components/connection/DestinationNamespaceModal/useExampleSettingsTable.ts delete mode 100644 airbyte-webapp/src/components/connection/DestinationStreamNamesModal/DestinationStreamNamesModal.module.scss delete mode 100644 airbyte-webapp/src/components/connection/DestinationStreamNamesModal/DestinationStreamNamesModal.tsx delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/JobProgress.module.scss delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/JobProgress.tsx delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/JobProgressLine.module.scss delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/JobProgressLine.tsx delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/StreamProgress.module.scss delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/StreamProgress.tsx delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/index.tsx delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/utils.test.ts delete mode 100644 airbyte-webapp/src/components/connection/JobProgress/utils.ts delete mode 100644 airbyte-webapp/src/components/connection/TransformationForm/TransformationForm.module.scss delete mode 100644 airbyte-webapp/src/components/connection/TransformationForm/TransformationForm.tsx delete mode 100644 airbyte-webapp/src/components/connection/TransformationForm/index.tsx delete mode 100644 airbyte-webapp/src/components/connection/TransformationForm/utils.test.ts delete mode 100644 airbyte-webapp/src/components/connection/TransformationForm/utils.ts delete mode 100644 airbyte-webapp/src/components/connection/UpdateConnectionDataResidency/UpdateConnectionDataResidency.module.scss delete mode 100644 airbyte-webapp/src/components/connection/UpdateConnectionDataResidency/UpdateConnectionDataResidency.tsx delete mode 100644 airbyte-webapp/src/components/connection/UpdateConnectionDataResidency/index.ts delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/AddStreamButton.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/AddStreamButton.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/AuthenticationSection.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/Builder.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/Builder.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderCard.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderCard.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderConfigView.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderConfigView.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderField.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderField.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderFieldWithInputs.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderFieldWithInputs.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderList.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderList.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderOneOf.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderOptional.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderOptional.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderSidebar.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderSidebar.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderTitle.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/BuilderTitle.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/GlobalConfigView.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/GlobalConfigView.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/InjectRequestOptionFields.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/InputsForm.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/InputsForm.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/InputsView.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/InputsView.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/KeyValueListField.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/KeyValueListField.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/PaginationSection.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/RemoveButton.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/RemoveButton.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/StreamConfigView.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/StreamConfigView.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/StreamReferenceField.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/StreamSlicerSection.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/ToggleGroupField.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/ToggleGroupField.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/UiYamlToggleButton.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/UiYamlToggleButton.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/UserInputField.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/Builder/UserInputField.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/BuilderPrompt.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/BuilderPrompt.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/DownloadYamlButton.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/DownloadYamlButton.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/SchemaConflictIndicator.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/SchemaConflictIndicator.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/ConfigMenu.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/ConfigMenu.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/ConfigMenuErrorBoundary.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/ConfigMenuErrorBoundary.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/LogsDisplay.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/LogsDisplay.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/PageDisplay.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/PageDisplay.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/ResultDisplay.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/ResultDisplay.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/SchemaDiffView.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/SchemaDiffView.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/SliceSelector.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/SliceSelector.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamSelector.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamSelector.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamTestButton.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamTestButton.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamTester.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamTester.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamTestingPanel.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/StreamTestingPanel.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/StreamTestingPanel/index.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/YamlEditor/YamlEditor.module.scss delete mode 100644 airbyte-webapp/src/components/connectorBuilder/YamlEditor/YamlEditor.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/YamlEditor/index.tsx delete mode 100644 airbyte-webapp/src/components/connectorBuilder/builder-prompt-icon.svg delete mode 100644 airbyte-webapp/src/components/connectorBuilder/types.ts delete mode 100644 airbyte-webapp/src/components/connectorBuilder/useBuilderErrors.ts delete mode 100644 airbyte-webapp/src/components/connectorBuilder/useManifestToBuilderForm.test.ts delete mode 100644 airbyte-webapp/src/components/connectorBuilder/useManifestToBuilderForm.ts delete mode 100644 airbyte-webapp/src/components/connectorBuilder/utils.ts delete mode 100644 airbyte-webapp/src/components/destination/DestinationConnectionTable/DestinationConnectionTable.module.scss delete mode 100644 airbyte-webapp/src/components/destination/DestinationConnectionTable/DestinationConnectionTable.tsx delete mode 100644 airbyte-webapp/src/components/destination/DestinationConnectionTable/index.ts delete mode 100644 airbyte-webapp/src/components/destination/DestinationForm/DestinationForm.tsx delete mode 100644 airbyte-webapp/src/components/destination/DestinationForm/index.ts delete mode 100644 airbyte-webapp/src/components/destination/DestinationsTable/DestinationsTable.tsx delete mode 100644 airbyte-webapp/src/components/destination/DestinationsTable/index.ts delete mode 100644 airbyte-webapp/src/components/icons/ArrowRightIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/CreditsIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/CrossIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/DocsIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/GAIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/InfoIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/MinusIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/ModificationIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/MoonIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/PauseIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/PencilIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/PlayIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/PlusIcon.tsx delete mode 100644 airbyte-webapp/src/components/icons/RotateIcon.tsx delete mode 100644 airbyte-webapp/src/components/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Banner/AlertBanner.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Banner/AlertBanner.tsx delete mode 100644 airbyte-webapp/src/components/ui/Banner/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/BarChart/BarChart.tsx delete mode 100644 airbyte-webapp/src/components/ui/BarChart/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/BarChart/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Breadcrumbs/Breadcrumbs.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Breadcrumbs/Breadcrumbs.tsx delete mode 100644 airbyte-webapp/src/components/ui/Breadcrumbs/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Breadcrumbs/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Button/Button.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Button/Button.tsx delete mode 100644 airbyte-webapp/src/components/ui/Button/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Button/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Button/types.tsx delete mode 100644 airbyte-webapp/src/components/ui/Callout/Callout.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Callout/Callout.tsx delete mode 100644 airbyte-webapp/src/components/ui/Callout/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Callout/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Card/Card.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Card/Card.tsx delete mode 100644 airbyte-webapp/src/components/ui/Card/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Card/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/CheckBox/CheckBox.module.scss delete mode 100644 airbyte-webapp/src/components/ui/CheckBox/CheckBox.tsx delete mode 100644 airbyte-webapp/src/components/ui/CheckBox/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/CheckBox/index.ts delete mode 100644 airbyte-webapp/src/components/ui/CodeEditor/CodeEditor.module.scss delete mode 100644 airbyte-webapp/src/components/ui/CodeEditor/CodeEditor.tsx delete mode 100644 airbyte-webapp/src/components/ui/CodeEditor/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/CodeEditor/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/CollapsibleCard/CollapsibleCard.tsx delete mode 100644 airbyte-webapp/src/components/ui/CollapsibleCard/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/CollapsibleCard/index.ts delete mode 100644 airbyte-webapp/src/components/ui/DatePicker/DatePicker.module.scss delete mode 100644 airbyte-webapp/src/components/ui/DatePicker/DatePicker.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/DatePicker/DatePicker.tsx delete mode 100644 airbyte-webapp/src/components/ui/DatePicker/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/DatePicker/index.ts delete mode 100644 airbyte-webapp/src/components/ui/DropDown/CustomSelect.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/DropDown.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/SelectContainer.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/components/DropDownText.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/components/DropdownIndicator.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/components/Menu.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/components/Option.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/components/SingleValue.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropDown/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropdownMenu/DropdownMenu.module.scss delete mode 100644 airbyte-webapp/src/components/ui/DropdownMenu/DropdownMenu.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropdownMenu/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/DropdownMenu/types.ts delete mode 100644 airbyte-webapp/src/components/ui/Flex/Flex.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Flex/FlexContainer.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Flex/FlexContainer.tsx delete mode 100644 airbyte-webapp/src/components/ui/Flex/FlexItem.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Flex/FlexItem.tsx delete mode 100644 airbyte-webapp/src/components/ui/Flex/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Heading/Heading.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Heading/Heading.tsx delete mode 100644 airbyte-webapp/src/components/ui/Heading/heading.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Heading/index.ts delete mode 100644 airbyte-webapp/src/components/ui/ImageBlock/ImageBlock.module.scss delete mode 100644 airbyte-webapp/src/components/ui/ImageBlock/ImageBlock.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/ImageBlock/ImageBlock.tsx delete mode 100644 airbyte-webapp/src/components/ui/ImageBlock/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/InfoText/InfoText.module.scss delete mode 100644 airbyte-webapp/src/components/ui/InfoText/InfoText.tsx delete mode 100644 airbyte-webapp/src/components/ui/InfoText/constants.ts delete mode 100644 airbyte-webapp/src/components/ui/InfoText/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/InfoText/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Input/Input.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Input/Input.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/Input/Input.tsx delete mode 100644 airbyte-webapp/src/components/ui/Input/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Input/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/ListBox/CaretDownIcon.svg delete mode 100644 airbyte-webapp/src/components/ui/ListBox/ListBox.module.scss delete mode 100644 airbyte-webapp/src/components/ui/ListBox/ListBox.tsx delete mode 100644 airbyte-webapp/src/components/ui/ListBox/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/ListBox/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/LoadingBackdrop/LoadingBackdrop.module.scss delete mode 100644 airbyte-webapp/src/components/ui/LoadingBackdrop/LoadingBackdrop.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/LoadingBackdrop/LoadingBackdrop.tsx delete mode 100644 airbyte-webapp/src/components/ui/LoadingBackdrop/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/LoadingBackdrop/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Markdown/Markdown.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Markdown/Markdown.tsx delete mode 100644 airbyte-webapp/src/components/ui/Markdown/admonitions.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Markdown/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Markdown/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Markdown/remarkAdmonitionsPlugin.ts delete mode 100644 airbyte-webapp/src/components/ui/Modal/Modal.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Modal/Modal.tsx delete mode 100644 airbyte-webapp/src/components/ui/Modal/ModalBody.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Modal/ModalBody.tsx delete mode 100644 airbyte-webapp/src/components/ui/Modal/ModalFooter.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Modal/ModalFooter.tsx delete mode 100644 airbyte-webapp/src/components/ui/Modal/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Modal/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Multiselect/Multiselect.tsx delete mode 100644 airbyte-webapp/src/components/ui/Multiselect/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/NextTable/NextTable.module.scss delete mode 100644 airbyte-webapp/src/components/ui/NextTable/NextTable.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/NextTable/NextTable.tsx delete mode 100644 airbyte-webapp/src/components/ui/NextTable/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/NextTable/index.ts delete mode 100644 airbyte-webapp/src/components/ui/NextTable/types.ts delete mode 100644 airbyte-webapp/src/components/ui/NumberBadge/NumberBadge.module.scss delete mode 100644 airbyte-webapp/src/components/ui/NumberBadge/NumberBadge.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/NumberBadge/NumberBadge.tsx delete mode 100644 airbyte-webapp/src/components/ui/NumberBadge/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Overlay/Overlay.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Overlay/Overlay.tsx delete mode 100644 airbyte-webapp/src/components/ui/Overlay/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Overlay/index.ts delete mode 100644 airbyte-webapp/src/components/ui/PageHeader/PageHeader.module.scss delete mode 100644 airbyte-webapp/src/components/ui/PageHeader/PageHeader.tsx delete mode 100644 airbyte-webapp/src/components/ui/PageHeader/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/PageHeader/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Paginator/Paginator.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Paginator/Paginator.tsx delete mode 100644 airbyte-webapp/src/components/ui/Paginator/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/PillSelect/PillButton.module.scss delete mode 100644 airbyte-webapp/src/components/ui/PillSelect/PillButton.tsx delete mode 100644 airbyte-webapp/src/components/ui/PillSelect/PillSelect.tsx delete mode 100644 airbyte-webapp/src/components/ui/PillSelect/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/PillSelect/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Popout/Popout.tsx delete mode 100644 airbyte-webapp/src/components/ui/Popout/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Popout/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/ProgressBar/ProgressBar.tsx delete mode 100644 airbyte-webapp/src/components/ui/ProgressBar/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/ProgressBar/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/RadioButton/RadioButton.tsx delete mode 100644 airbyte-webapp/src/components/ui/RadioButton/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/RadioButton/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/ResizablePanels/ResizablePanels.module.scss delete mode 100644 airbyte-webapp/src/components/ui/ResizablePanels/ResizablePanels.tsx delete mode 100644 airbyte-webapp/src/components/ui/ResizablePanels/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/SecretTextArea/SecretTextArea.module.scss delete mode 100644 airbyte-webapp/src/components/ui/SecretTextArea/SecretTextArea.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/SecretTextArea/SecretTextArea.tsx delete mode 100644 airbyte-webapp/src/components/ui/SecretTextArea/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/SecretTextArea/index.ts delete mode 100644 airbyte-webapp/src/components/ui/SideMenu/MenuItem.tsx delete mode 100644 airbyte-webapp/src/components/ui/SideMenu/SideMenu.tsx delete mode 100644 airbyte-webapp/src/components/ui/SideMenu/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/SideMenu/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/SlickSlider/SlickSlider.module.scss delete mode 100644 airbyte-webapp/src/components/ui/SlickSlider/SlickSlider.tsx delete mode 100644 airbyte-webapp/src/components/ui/SlickSlider/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/SlickSlider/index.ts delete mode 100644 airbyte-webapp/src/components/ui/SlickSlider/slider.css delete mode 100644 airbyte-webapp/src/components/ui/Spinner/Spinner.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Spinner/Spinner.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/Spinner/Spinner.tsx delete mode 100644 airbyte-webapp/src/components/ui/Spinner/__snapshots__/Spinner.test.tsx.snap delete mode 100644 airbyte-webapp/src/components/ui/Spinner/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Spinner/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/StatusIcon/CircleLoader.module.scss delete mode 100644 airbyte-webapp/src/components/ui/StatusIcon/CircleLoader.tsx delete mode 100644 airbyte-webapp/src/components/ui/StatusIcon/StatusIcon.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/StatusIcon/StatusIcon.tsx delete mode 100644 airbyte-webapp/src/components/ui/StatusIcon/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/StatusIcon/index.ts delete mode 100644 airbyte-webapp/src/components/ui/StepsIndicator/StepsIndicator.module.scss delete mode 100644 airbyte-webapp/src/components/ui/StepsIndicator/StepsIndicator.tsx delete mode 100644 airbyte-webapp/src/components/ui/StepsIndicator/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/StepsIndicator/index.ts delete mode 100644 airbyte-webapp/src/components/ui/StepsMenu/Step.tsx delete mode 100644 airbyte-webapp/src/components/ui/StepsMenu/StepsMenu.tsx delete mode 100644 airbyte-webapp/src/components/ui/StepsMenu/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/StepsMenu/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Switch/Progress.svg delete mode 100644 airbyte-webapp/src/components/ui/Switch/ProgressReverse.svg delete mode 100644 airbyte-webapp/src/components/ui/Switch/Switch.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Switch/Switch.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Switch/Switch.tsx delete mode 100644 airbyte-webapp/src/components/ui/Switch/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Table/SortableTableHeader/SortableTableHeader.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Table/SortableTableHeader/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Table/Table.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Table/Table.tsx delete mode 100644 airbyte-webapp/src/components/ui/Table/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Table/index.ts delete mode 100644 airbyte-webapp/src/components/ui/TagInput/TagInput.module.scss delete mode 100644 airbyte-webapp/src/components/ui/TagInput/TagInput.test.tsx delete mode 100644 airbyte-webapp/src/components/ui/TagInput/TagInput.tsx delete mode 100644 airbyte-webapp/src/components/ui/TagInput/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Text/Text.tsx delete mode 100644 airbyte-webapp/src/components/ui/Text/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Text/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Text/text.module.scss delete mode 100644 airbyte-webapp/src/components/ui/TextArea/TextArea.module.scss delete mode 100644 airbyte-webapp/src/components/ui/TextArea/TextArea.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextArea/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextArea/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextInputContainer/TextInputContainer.module.scss delete mode 100644 airbyte-webapp/src/components/ui/TextInputContainer/TextInputContainer.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextInputContainer/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextInputContainer/index.ts delete mode 100644 airbyte-webapp/src/components/ui/TextWithHTML/TextWithHTML.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextWithHTML/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/TextWithHTML/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Toast/Toast.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Toast/Toast.tsx delete mode 100644 airbyte-webapp/src/components/ui/Toast/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Toast/index.tsx delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/InfoTooltip.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/InfoTooltip.tsx delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/Tooltip.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/Tooltip.tsx delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/TooltipLearnMoreLink.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/TooltipLearnMoreLink.tsx delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/TooltipTable.module.scss delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/TooltipTable.tsx delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/context.ts delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/index.stories.tsx delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/index.ts delete mode 100644 airbyte-webapp/src/components/ui/Tooltip/types.ts delete mode 100644 airbyte-webapp/src/config/ConfigServiceProvider.tsx delete mode 100644 airbyte-webapp/src/config/availableCronTimeZones.json delete mode 100644 airbyte-webapp/src/config/casesConfig.json delete mode 100644 airbyte-webapp/src/config/config.ts delete mode 100644 airbyte-webapp/src/config/frequencyConfig.ts delete mode 100644 airbyte-webapp/src/config/index.ts delete mode 100644 airbyte-webapp/src/config/types.ts delete mode 100644 airbyte-webapp/src/core/ApiServices.tsx delete mode 100644 airbyte-webapp/src/core/analytics/AnalyticsService.test.ts delete mode 100644 airbyte-webapp/src/core/analytics/AnalyticsService.ts delete mode 100644 airbyte-webapp/src/core/analytics/index.ts delete mode 100644 airbyte-webapp/src/core/analytics/types.ts delete mode 100644 airbyte-webapp/src/core/analytics/utils.ts delete mode 100644 airbyte-webapp/src/core/domain/Documentation.test.ts delete mode 100644 airbyte-webapp/src/core/domain/Documentation.ts delete mode 100644 airbyte-webapp/src/core/domain/catalog/api.ts delete mode 100644 airbyte-webapp/src/core/domain/catalog/index.tsx delete mode 100644 airbyte-webapp/src/core/domain/catalog/models.ts delete mode 100644 airbyte-webapp/src/core/domain/catalog/traverseSchemaToField.test.ts delete mode 100644 airbyte-webapp/src/core/domain/catalog/traverseSchemaToField.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/ConnectionService.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/OperationService.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/WebBackendConnectionService.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/index.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/operation.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/types.ts delete mode 100644 airbyte-webapp/src/core/domain/connection/utils.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/DestinationAuthService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/DestinationDefinitionService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/DestinationDefinitionSpecificationService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/DestinationService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/SourceAuthService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/SourceDefinitionService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/SourceDefinitionSpecificationService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/SourceService.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/connector.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/constants.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/destination.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/index.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/source.ts delete mode 100644 airbyte-webapp/src/core/domain/connector/types.ts delete mode 100644 airbyte-webapp/src/core/domain/connectorBuilder/ConnectorBuilderRequestService.ts delete mode 100644 airbyte-webapp/src/core/domain/job/Job.ts delete mode 100644 airbyte-webapp/src/core/domain/job/JobsService.tsx delete mode 100644 airbyte-webapp/src/core/domain/job/index.ts delete mode 100644 airbyte-webapp/src/core/domain/logs/LogsService.tsx delete mode 100644 airbyte-webapp/src/core/domain/logs/types.ts delete mode 100644 airbyte-webapp/src/core/domain/notification/NotificationService.tsx delete mode 100644 airbyte-webapp/src/core/domain/workspace/Workspace.ts delete mode 100644 airbyte-webapp/src/core/domain/workspace/WorkspaceService.ts delete mode 100644 airbyte-webapp/src/core/domain/workspace/index.ts delete mode 100644 airbyte-webapp/src/core/form/FormBuildError.ts delete mode 100644 airbyte-webapp/src/core/form/FormikPatch.ts delete mode 100644 airbyte-webapp/src/core/form/schemaToFormBlock.test.ts delete mode 100644 airbyte-webapp/src/core/form/schemaToFormBlock.ts delete mode 100644 airbyte-webapp/src/core/form/schemaToYup.test.ts delete mode 100644 airbyte-webapp/src/core/form/schemaToYup.ts delete mode 100644 airbyte-webapp/src/core/form/types.ts delete mode 100644 airbyte-webapp/src/core/health/HealthService.ts delete mode 100644 airbyte-webapp/src/core/i18n/I18nProvider.test.tsx delete mode 100644 airbyte-webapp/src/core/i18n/I18nProvider.tsx delete mode 100644 airbyte-webapp/src/core/i18n/index.ts delete mode 100644 airbyte-webapp/src/core/jsonSchema/types.ts delete mode 100644 airbyte-webapp/src/core/request/AirbyteRequestService.ts delete mode 100644 airbyte-webapp/src/core/request/CommonRequestError.ts delete mode 100644 airbyte-webapp/src/core/request/LogsRequestError.ts delete mode 100644 airbyte-webapp/src/core/request/RequestMiddleware.ts delete mode 100644 airbyte-webapp/src/core/request/ServerError.ts delete mode 100644 airbyte-webapp/src/core/request/VersionError.ts delete mode 100644 airbyte-webapp/src/core/request/apiOverride.ts delete mode 100644 airbyte-webapp/src/core/request/pollUntil.test.ts delete mode 100644 airbyte-webapp/src/core/request/pollUntil.ts delete mode 100644 airbyte-webapp/src/core/servicesProvider.tsx delete mode 100644 airbyte-webapp/src/dayjs-setup.ts delete mode 100644 airbyte-webapp/src/hooks/connection/useConfirmCatalogDiff.tsx delete mode 100644 airbyte-webapp/src/hooks/connection/useDestinationNamespace.ts delete mode 100644 airbyte-webapp/src/hooks/connection/useNewTableDesignExperiment.ts delete mode 100644 airbyte-webapp/src/hooks/connection/useSchemaChanges.ts delete mode 100644 airbyte-webapp/src/hooks/domain/connector/useAvailableConnectorDefinitions.ts delete mode 100644 airbyte-webapp/src/hooks/router/useBlocker.ts delete mode 100644 airbyte-webapp/src/hooks/services/Analytics/__mocks__/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/Analytics/__mocks__/useAnalyticsService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Analytics/index.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Analytics/pageTrackingCodes.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Analytics/useAnalyticsService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/AppMonitoringService/AppMonitoringService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/AppMonitoringService/__mocks__/AppMonitoringService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/AppMonitoringService/__mocks__/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/AppMonitoringService/actionCodes.ts delete mode 100644 airbyte-webapp/src/hooks/services/AppMonitoringService/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/BulkEdit/BulkEditService.test.tsx delete mode 100644 airbyte-webapp/src/hooks/services/BulkEdit/BulkEditService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/ConfirmationModal/ConfirmationModalService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/ConfirmationModal/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/ConfirmationModal/reducer.ts delete mode 100644 airbyte-webapp/src/hooks/services/ConfirmationModal/types.ts delete mode 100644 airbyte-webapp/src/hooks/services/ConnectionEdit/ConnectionEditService.test.tsx delete mode 100644 airbyte-webapp/src/hooks/services/ConnectionEdit/ConnectionEditService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/ConnectionForm/ConnectionFormService.test.tsx delete mode 100644 airbyte-webapp/src/hooks/services/ConnectionForm/ConnectionFormService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Experiment/ExperimentService.test.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Experiment/ExperimentService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Experiment/experiments.ts delete mode 100644 airbyte-webapp/src/hooks/services/Experiment/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/Feature/FeatureService.test.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Feature/FeatureService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Feature/constants.ts delete mode 100644 airbyte-webapp/src/hooks/services/Feature/index.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Feature/types.tsx delete mode 100644 airbyte-webapp/src/hooks/services/FormChangeTracker/FormChangeTrackerService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/FormChangeTracker/hooks.test.ts delete mode 100644 airbyte-webapp/src/hooks/services/FormChangeTracker/hooks.ts delete mode 100644 airbyte-webapp/src/hooks/services/FormChangeTracker/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/FormChangeTracker/types.ts delete mode 100644 airbyte-webapp/src/hooks/services/Health/HealthPollService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Health/index.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Modal/ModalService.test.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Modal/ModalService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Modal/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/Modal/types.ts delete mode 100644 airbyte-webapp/src/hooks/services/Notification/NotificationService.tsx delete mode 100644 airbyte-webapp/src/hooks/services/Notification/index.ts delete mode 100644 airbyte-webapp/src/hooks/services/Notification/reducer.ts delete mode 100644 airbyte-webapp/src/hooks/services/Notification/types.ts delete mode 100644 airbyte-webapp/src/hooks/services/useBuildUpdateCheck.ts delete mode 100644 airbyte-webapp/src/hooks/services/useConnectionHook.tsx delete mode 100644 airbyte-webapp/src/hooks/services/useConnector.tsx delete mode 100644 airbyte-webapp/src/hooks/services/useConnectorAuth.tsx delete mode 100644 airbyte-webapp/src/hooks/services/useDestinationHook.tsx delete mode 100644 airbyte-webapp/src/hooks/services/useDocumentation.ts delete mode 100644 airbyte-webapp/src/hooks/services/useRequestConnector.tsx delete mode 100644 airbyte-webapp/src/hooks/services/useSourceHook.tsx delete mode 100644 airbyte-webapp/src/hooks/services/useWorkspace.tsx delete mode 100644 airbyte-webapp/src/hooks/useDeleteModal.tsx delete mode 100644 airbyte-webapp/src/hooks/useLoadingState.tsx delete mode 100644 airbyte-webapp/src/hooks/useQuery.ts delete mode 100644 airbyte-webapp/src/hooks/useSegment.tsx delete mode 100644 airbyte-webapp/src/hooks/useTypesafeReducer.ts delete mode 100644 airbyte-webapp/src/index.tsx delete mode 100644 airbyte-webapp/src/locales/en.json delete mode 100644 airbyte-webapp/src/packages/cloud/App.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/README.md delete mode 100644 airbyte-webapp/src/packages/cloud/cloudRoutePaths.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/cloudRoutes.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/EnrollmentModal.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/EnrollmentModal.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/cards.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/connectorGrid.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/free-alpha-beta-pills.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/free.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/mail.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/EnrollmentModal/useShowEnrollmentModal.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/FreeTag.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/FreeTag.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/InlineEnrollmentCallout.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/InlineEnrollmentCallout.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/LargeEnrollmentCallout.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/LargeEnrollmentCallout.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/connectors-badges.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/hooks/useFreeConnectorProgram.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/lib/api.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/lib/model.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/FreeConnectorProgram/longtail-connectors.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/CountDownTimer/CountDownTimer.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/CountDownTimer/CountDownTimer.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/CountDownTimer/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/CountDownTimer/useCountdown.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/SpeedyConnectionBanner/SpeedyConnectionBanner.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/SpeedyConnectionBanner/SpeedyConnectionBanner.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/SpeedyConnectionBanner/credits.svg delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/SpeedyConnectionBanner/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/components/experiments/SpeedyConnection/hooks/useExperimentSpeedyConnection.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/auth/AuthProviders.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/auth/GoogleAuthService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/auth/RequestAuthMiddleware.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/cloudWorkspaces/CloudWorkspacesService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/cloudWorkspaces/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/dbtCloud/api.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/dbtCloud/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/geographies/GeographiesService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/speakeasy/api.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/speakeasy/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/stripe/StripeService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/stripe/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/stripe/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/users/UserService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/users/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/domain/users/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/lib/errors/FieldError.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/locales/en.json delete mode 100644 airbyte-webapp/src/packages/cloud/package.json delete mode 100644 airbyte-webapp/src/packages/cloud/services/AppServicesProvider.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/FirebaseSdkProvider.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/auth/AuthService.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/auth/freeEmailProviders.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/auth/reducer.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/auth/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/dbtCloud.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/geographies/GeographiesService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/speakeasy/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/speakeasy/useSpeakeasyRedirect.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/stripe/StripeService.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/thirdParty/intercom/IntercomProvider.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/thirdParty/intercom/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/thirdParty/intercom/useIntercom.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/thirdParty/launchdarkly/LDExperimentService.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/thirdParty/launchdarkly/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/users/InviteUsersModalService.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/users/UseUserHook.ts delete mode 100644 airbyte-webapp/src/packages/cloud/services/users/UserService.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/services/workspaces/CloudWorkspacesService.ts delete mode 100644 airbyte-webapp/src/packages/cloud/theme.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/AcceptEmailInvite.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/DefaultView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/FirebaseActionRoute.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/Auth.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/Auth.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/ConfirmPasswordResetPage/ConfirmPasswordResetPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/ConfirmPasswordResetPage/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/LoginPage/LoginPage.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/LoginPage/LoginPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/LoginPage/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/OAuthLogin/OAuthLogin.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/OAuthLogin/OAuthLogin.test.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/OAuthLogin/OAuthLogin.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/OAuthLogin/assets/github-logo.svg delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/OAuthLogin/assets/google-logo.svg delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/OAuthLogin/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/ResetPasswordPage/ResetPasswordPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/ResetPasswordPage/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/SignupPage.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/SignupPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/Separator.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/Separator.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/SignupForm.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/SignupForm.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/SimpleLeftSide/SimpleLeftSide.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/SimpleLeftSide/SimpleLeftSide.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/SpecialBlock.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/components/SpecialBlock.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/SignupPage/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/CheckBoxControl.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/FormComponents.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/FormContent.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/FormTitle/FormTitle.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/FormTitle/FormTitle.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/FormTitle/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/GitBlock/GitBlock.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/GitBlock/GitBlock.test.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/GitBlock/GitBlock.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/GitBlock/__snapshots__/GitBlock.test.tsx.snap delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/GitBlock/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/Header/Header.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/Header/Header.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/Header/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/PersonQuoteCover/PersonQuoteCover.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/PersonQuoteCover/PersonQuoteCover.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/components/PersonQuoteCover/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/auth/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/CreditsPage.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/CreditsPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/ConnectionCell.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/ConnectionCell.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/CreditsUsage.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/CreditsUsage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/EmailVerificationHint.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/LowCreditBalanceHint/LowCreditBalanceHint.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/LowCreditBalanceHint/LowCreditBalanceHint.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/LowCreditBalanceHint/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/RemainingCredits.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsageCell.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/credits/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/layout/CloudMainView/CloudMainView.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/layout/CloudMainView/CloudMainView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/layout/CloudMainView/CloudResourcesDropdown.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/layout/CloudMainView/CloudSupportDropdown.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/layout/CloudMainView/InsufficientPermissionsErrorBoundary.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/layout/CloudMainView/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/settings/CloudSettingsPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/settings/integrations/DbtCloudSettingsView.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/settings/integrations/DbtCloudSettingsView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/settings/routePaths.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/AccountSettingsView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/EmailSection/EmailSection.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/EmailSection/hooks/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/EmailSection/hooks/useEmail.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/EmailSection/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/EmailSection/typings.d.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/NameSection/NameSection.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/NameSection/hooks/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/NameSection/hooks/useName.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/NameSection/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/NameSection/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/PasswordSection/PasswordSection.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/PasswordSection/hooks/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/PasswordSection/hooks/usePassword.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/PasswordSection/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/PasswordSection/typings.d.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/components/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/AccountSettingsView/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersHint/InviteUsersHint.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersHint/InviteUsersHint.test.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersHint/InviteUsersHint.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersHint/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersHint/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersModal/InviteUsersModal.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersModal/InviteUsersModal.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersModal/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/InviteUsersModal/types.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/UsersSettingsView.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/UsersSettingsView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/components/RoleToolTip.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/DataResidencyView/DataResidencyView.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/DataResidencyView/DataResidencyView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/DataResidencyView/index.ts delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacePopout/WorkspacePopout.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacePopout/components/ExitIcon.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacePopout/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspaceSettingsView/WorkspaceSettingsView.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspaceSettingsView/WorkspaceSettingsView.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspaceSettingsView/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/WorkspacesPage.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/WorkspacesPage.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/components/CreateWorkspaceForm.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/components/WorkspaceControl.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/components/WorkspaceItem.module.scss delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/components/WorkspaceItem.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/components/WorkspacesControl.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/components/WorkspacesList.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/WorkspacesPage/index.tsx delete mode 100644 airbyte-webapp/src/packages/cloud/views/workspaces/index.tsx delete mode 100644 airbyte-webapp/src/packages/firebaseReact/firebaseApp.tsx delete mode 100644 airbyte-webapp/src/packages/firebaseReact/index.tsx delete mode 100644 airbyte-webapp/src/packages/firebaseReact/sdk.tsx delete mode 100644 airbyte-webapp/src/pages/PreferencesPage/PreferencesPage.module.scss delete mode 100644 airbyte-webapp/src/pages/PreferencesPage/PreferencesPage.tsx delete mode 100644 airbyte-webapp/src/pages/PreferencesPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/SettingsPage.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/SettingsPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/components/FeedbackBlock.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/components/useWorkspaceEditor.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/AccountPage/AccountPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/AccountPage/components/AccountForm.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/AccountPage/components/AccountForm.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/AccountPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConfigurationsPage/ConfigurationsPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConfigurationsPage/components/ImportConfigurationModal.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConfigurationsPage/components/LogsContainer.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConfigurationsPage/components/LogsContent.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConfigurationsPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/DestinationsPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/SourcesPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorCell.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorCell.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsViewContext.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/CreateConnector.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/CreateConnectorModal.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/CreateConnectorModal.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ImageCell.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ImageCell.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/UpgradeAllButton.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/UpgradeAllButton.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/VersionCell.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/VersionCell.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/builder-icon.svg delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/MetricsPage/MetricsPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/MetricsPage/components/MetricsForm.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/MetricsPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/NotificationPage/NotificationPage.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/NotificationPage/components/NotificationsForm.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/NotificationPage/components/WebHookForm.module.scss delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/NotificationPage/components/WebHookForm.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/NotificationPage/components/help.png delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/NotificationPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SettingsPage/pages/SettingsComponents.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/SourcesPage.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/AllSourcesPage/AllSourcesPage.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/AllSourcesPage/components/SourcesTable.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/AllSourcesPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/CreateSourcePage/CreateSourcePage.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/CreateSourcePage/components/SourceForm.module.scss delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/CreateSourcePage/components/SourceForm.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/SourceItemPage.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.module.scss delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceSettings.module.scss delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceSettings.tsx delete mode 100644 airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/SpeakeasyRedirectPage/SpeakeasyRedirectPage.tsx delete mode 100644 airbyte-webapp/src/pages/SpeakeasyRedirectPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/connections/AllConnectionsPage/AllConnectionsPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/AllConnectionsPage/AllConnectionsPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/AllConnectionsPage/ConnectionsTable.tsx delete mode 100644 airbyte-webapp/src/pages/connections/AllConnectionsPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionPage/ConnectionPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionPage/ConnectionPageTitle.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionPage/ConnectionPageTitle.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ConnectionReplicationPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ConnectionReplicationPage.test.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ConnectionReplicationPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ResetWarningModal.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionReplicationPage/__snapshots__/ConnectionReplicationPage.test.tsx.snap delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionReplicationPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionSettingsPage/ConnectionSettingsPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionSettingsPage/ConnectionSettingsPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionSettingsPage/SchemaUpdateNotifications.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionSettingsPage/SchemaUpdateNotifications.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionSettingsPage/StateBlock.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionSettingsPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionStatusPage/ConnectionStatusPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionStatusPage/ConnectionStatusPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionStatusPage/JobsList.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionStatusPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/ConnectionTransformationPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/ConnectionTransformationPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/CustomTransformationsCard.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/DbtCloudCard.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/DbtCloudTransformationsCard.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/DbtJobsForm.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/DbtJobsForm.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/JobsList.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/JobsList.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/JobsListItem.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/JobsListItem.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/NoDbtIntegration.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/NoDbtIntegration.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/dbt-bit_tm.svg delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/DbtCloudTransformationsCard/octavia-worker.png delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/NormalizationCard.tsx delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionTransformationPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/ConnectionsRoutes.tsx delete mode 100644 airbyte-webapp/src/pages/connections/CreateConnectionPage/ConnectionCreateDestinationForm.tsx delete mode 100644 airbyte-webapp/src/pages/connections/CreateConnectionPage/ConnectionCreateSourceForm.tsx delete mode 100644 airbyte-webapp/src/pages/connections/CreateConnectionPage/CreateConnectionPage.tsx delete mode 100644 airbyte-webapp/src/pages/connections/CreateConnectionPage/ExistingEntityForm.module.scss delete mode 100644 airbyte-webapp/src/pages/connections/CreateConnectionPage/ExistingEntityForm.tsx delete mode 100644 airbyte-webapp/src/pages/connections/CreateConnectionPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connections/types.ts delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderEditPage/ConnectorBuilderEditPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderEditPage/ConnectorBuilderEditPage.tsx delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderEditPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/ConnectorBuilderLandingPage.module.scss delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/ConnectorBuilderLandingPage.tsx delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/airbyte-logo.svg delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/import-yaml.svg delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/index.ts delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/load-existing-connector.svg delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderLandingPage/start-from-scratch.svg delete mode 100644 airbyte-webapp/src/pages/connectorBuilder/ConnectorBuilderRoutes.tsx delete mode 100644 airbyte-webapp/src/pages/destination/AllDestinationsPage/AllDestinationsPage.tsx delete mode 100644 airbyte-webapp/src/pages/destination/AllDestinationsPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/destination/CreateDestinationPage/CreateDestinationPage.tsx delete mode 100644 airbyte-webapp/src/pages/destination/CreateDestinationPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/destination/DestinationItemPage/DestinationItemPage.tsx delete mode 100644 airbyte-webapp/src/pages/destination/DestinationItemPage/index.tsx delete mode 100644 airbyte-webapp/src/pages/destination/DestinationOverviewPage.tsx delete mode 100644 airbyte-webapp/src/pages/destination/DestinationSettingsPage/DestinationSettings.module.scss delete mode 100644 airbyte-webapp/src/pages/destination/DestinationSettingsPage/DestinationSettingsPage.tsx delete mode 100644 airbyte-webapp/src/pages/destination/DestinationSettingsPage/index.ts delete mode 100644 airbyte-webapp/src/pages/destination/types.ts delete mode 100644 airbyte-webapp/src/pages/routePaths.tsx delete mode 100644 airbyte-webapp/src/pages/routes.tsx delete mode 100644 airbyte-webapp/src/scss/_colors.scss delete mode 100644 airbyte-webapp/src/scss/_fonts.scss delete mode 100644 airbyte-webapp/src/scss/_mixins.scss delete mode 100644 airbyte-webapp/src/scss/_theme-light.scss delete mode 100644 airbyte-webapp/src/scss/_variables.scss delete mode 100644 airbyte-webapp/src/scss/_z-indices.scss delete mode 100644 airbyte-webapp/src/scss/export.module.scss delete mode 100644 airbyte-webapp/src/scss/global.scss delete mode 100644 airbyte-webapp/src/services/Scope.ts delete mode 100644 airbyte-webapp/src/services/connector/ConnectorDefinitions.ts delete mode 100644 airbyte-webapp/src/services/connector/ConnectorService.ts delete mode 100644 airbyte-webapp/src/services/connector/DestinationDefinitionService.ts delete mode 100644 airbyte-webapp/src/services/connector/DestinationDefinitionSpecificationService.tsx delete mode 100644 airbyte-webapp/src/services/connector/SourceDefinitionService.ts delete mode 100644 airbyte-webapp/src/services/connector/SourceDefinitionSpecificationService.tsx delete mode 100644 airbyte-webapp/src/services/connector/useSuspenseQuery.ts delete mode 100644 airbyte-webapp/src/services/connectorBuilder/ConnectorBuilderApiService.ts delete mode 100644 airbyte-webapp/src/services/connectorBuilder/ConnectorBuilderLocalStorageService.tsx delete mode 100644 airbyte-webapp/src/services/connectorBuilder/ConnectorBuilderStateService.tsx delete mode 100644 airbyte-webapp/src/services/connectorBuilder/connector_manifest_openapi.yaml delete mode 100644 airbyte-webapp/src/services/job/JobService.tsx delete mode 100644 airbyte-webapp/src/services/logs/LogsService.tsx delete mode 100644 airbyte-webapp/src/services/useDefaultRequestMiddlewares.tsx delete mode 100644 airbyte-webapp/src/services/useInitService.tsx delete mode 100644 airbyte-webapp/src/services/workspaces/WorkspacesService.tsx delete mode 100644 airbyte-webapp/src/test-utils/TestSuspenseBoundary.tsx delete mode 100644 airbyte-webapp/src/test-utils/classname-serializer.js delete mode 100644 airbyte-webapp/src/test-utils/index.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockAirbyteStreamConfiguration.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockCatalogDiff.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockConnection.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockDestination.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockDestinationDefinitionSpecification.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockEmpty.js delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockFrequentlyUsedDestinations.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockIdentity.js delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockSource.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockSourceDefinition.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockStartWithDestination.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockSvg.js delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockWorkspace.ts delete mode 100644 airbyte-webapp/src/test-utils/mock-data/mockWorkspaceId.ts delete mode 100644 airbyte-webapp/src/test-utils/setup-tests.ts delete mode 100644 airbyte-webapp/src/test-utils/testutils.tsx delete mode 100644 airbyte-webapp/src/theme.ts delete mode 100644 airbyte-webapp/src/types/formik.ts delete mode 100644 airbyte-webapp/src/types/react-widgets.d.ts delete mode 100644 airbyte-webapp/src/types/rehype-urls.d.ts delete mode 100644 airbyte-webapp/src/utils/__snapshots__/useTranslateDataType.test.tsx.snap delete mode 100644 airbyte-webapp/src/utils/app.ts delete mode 100644 airbyte-webapp/src/utils/clipboard.ts delete mode 100644 airbyte-webapp/src/utils/common.test.ts delete mode 100644 airbyte-webapp/src/utils/common.ts delete mode 100644 airbyte-webapp/src/utils/connectors/constants.ts delete mode 100644 airbyte-webapp/src/utils/connectors/destinations.json delete mode 100644 airbyte-webapp/src/utils/connectors/index.ts delete mode 100644 airbyte-webapp/src/utils/connectors/sources.json delete mode 100644 airbyte-webapp/src/utils/cron/index.ts delete mode 100644 airbyte-webapp/src/utils/cron/validateCronExpression.test.ts delete mode 100644 airbyte-webapp/src/utils/cron/validateCronExpression.ts delete mode 100644 airbyte-webapp/src/utils/crossDomainUtils.test.ts delete mode 100644 airbyte-webapp/src/utils/crossDomainUtils.ts delete mode 100644 airbyte-webapp/src/utils/dataPrivacy.test.ts delete mode 100644 airbyte-webapp/src/utils/dataPrivacy.ts delete mode 100644 airbyte-webapp/src/utils/datadog.ts delete mode 100644 airbyte-webapp/src/utils/errorStatusMessage.test.tsx delete mode 100644 airbyte-webapp/src/utils/errorStatusMessage.tsx delete mode 100644 airbyte-webapp/src/utils/file.ts delete mode 100644 airbyte-webapp/src/utils/imageUtils.tsx delete mode 100644 airbyte-webapp/src/utils/links.ts delete mode 100644 airbyte-webapp/src/utils/numberHelper.test.tsx delete mode 100644 airbyte-webapp/src/utils/numberHelper.tsx delete mode 100644 airbyte-webapp/src/utils/objects.ts delete mode 100644 airbyte-webapp/src/utils/promises.ts delete mode 100644 airbyte-webapp/src/utils/sentry.ts delete mode 100644 airbyte-webapp/src/utils/strings.test.ts delete mode 100644 airbyte-webapp/src/utils/strings.ts delete mode 100644 airbyte-webapp/src/utils/useTranslateDataType.test.tsx delete mode 100644 airbyte-webapp/src/utils/useTranslateDataType.ts delete mode 100644 airbyte-webapp/src/utils/withKeystrokeHandler.tsx delete mode 100644 airbyte-webapp/src/views/CompleteOauthRequest.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/ConnectorCard.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/ConnectorCard.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/Controls.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/ShowLoadingMessage.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/TestCard.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/TestCard.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/TestingConnectionSpinner.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/TestingConnectionSpinner.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/components/TestingConnectionSuccess.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/index.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/useAnalyticsTrackFunctions.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorCard/useTestConnector.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/ConnectorDocumentationLayout.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/ConnectorDocumentationLayout.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/ConnectorDocumentationWrapper.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/DocumentationPanel.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/DocumentationPanel.test.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/DocumentationPanel.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorDocumentationLayout/index.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/ConnectorForm.test.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/ConnectorForm.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/FormRoot.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/FormRoot.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Controls/ConnectorServiceTypeControl/ConnectorDefinitionTypeControl.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Controls/ConnectorServiceTypeControl/ConnectorServiceTypeControl.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Controls/ConnectorServiceTypeControl/index.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Controls/ConnectorServiceTypeControl/useAnalyticsTrackFunctions.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Controls/ConnectorServiceTypeControl/utils.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/FrequentlyUsedConnectors.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/FrequentlyUsedConnectorsCard.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/FrequentlyUsedConnectorsCard.test.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/FrequentlyUsedConnectorsCard.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/__snapshots__/FrequentlyUsedConnectorsCard.test.tsx.snap delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/index.stories.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/index.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/useAnalyticsTrackFunctions.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/FrequentlyUsedConnectors/useSuggestedConnectors.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/Control.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/LabelInfo.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/LabelInfo.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/PropertyError.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/PropertyError.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/PropertyLabel.stories.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/PropertyLabel.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/SecretConfirmationControl.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Property/SecretConfirmationControl.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/ArraySection.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/ConditionSection.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/ConditionSection.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/FormSection.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/GroupLabel.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/PropertySection.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/PropertySection.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/SectionContainer.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/SectionContainer.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/VariableInputFieldForm.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/AuthButton.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/AuthButton.test.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/AuthButton.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/AuthSection.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/GoogleAuthButton.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/Sections/auth/useOauthFlowAdapter.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/TestingConnectionError.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/WarningMessage.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/components/WarningMessage.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/connectorFormContext.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/index.stories.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/index.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/types.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/useAuthentication.mocks.ts delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/useAuthentication.test.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/useAuthentication.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/useBuildForm.tsx delete mode 100644 airbyte-webapp/src/views/Connector/ConnectorForm/utils.ts delete mode 100644 airbyte-webapp/src/views/Connector/RequestConnectorModal/RequestConnectorModal.module.scss delete mode 100644 airbyte-webapp/src/views/Connector/RequestConnectorModal/RequestConnectorModal.tsx delete mode 100644 airbyte-webapp/src/views/Connector/RequestConnectorModal/index.tsx delete mode 100644 airbyte-webapp/src/views/Connector/RequestConnectorModal/types.ts delete mode 100644 airbyte-webapp/src/views/Settings/PreferencesForm/PreferencesForm.tsx delete mode 100644 airbyte-webapp/src/views/Settings/PreferencesForm/components/EditControls.tsx delete mode 100644 airbyte-webapp/src/views/Settings/PreferencesForm/index.tsx delete mode 100644 airbyte-webapp/src/views/common/AnalyticsProvider.tsx delete mode 100644 airbyte-webapp/src/views/common/ErrorOccurredView/ErrorOccurredView.module.scss delete mode 100644 airbyte-webapp/src/views/common/ErrorOccurredView/ErrorOccurredView.tsx delete mode 100644 airbyte-webapp/src/views/common/ErrorOccurredView/index.tsx delete mode 100644 airbyte-webapp/src/views/common/ResorceNotFoundErrorBoundary.tsx delete mode 100644 airbyte-webapp/src/views/common/StartOverErrorView.tsx delete mode 100644 airbyte-webapp/src/views/common/StoreProvider.tsx delete mode 100644 airbyte-webapp/src/views/layout/MainView/MainView.module.scss delete mode 100644 airbyte-webapp/src/views/layout/MainView/MainView.tsx delete mode 100644 airbyte-webapp/src/views/layout/MainView/index.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/AirbyteHomeLink.module.scss delete mode 100644 airbyte-webapp/src/views/layout/SideBar/AirbyteHomeLink.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/MainNavItems.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/NotificationIndicator.module.scss delete mode 100644 airbyte-webapp/src/views/layout/SideBar/NotificationIndicator.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/SideBar.module.scss delete mode 100644 airbyte-webapp/src/views/layout/SideBar/SideBar.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/airbyteLogo.svg delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/BuilderIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/ChatIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/ConnectionsIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/DestinationIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/MenuContent.module.scss delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/MenuContent.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/NavDropdown.module.scss delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/NavDropdown.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/NavItem.module.scss delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/NavItem.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/RecipesIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/ResourcesDropdown.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/SettingsIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/SourceIcon.tsx delete mode 100644 airbyte-webapp/src/views/layout/SideBar/components/StatusIcon.tsx delete mode 100644 airbyte-webapp/src/vite-env.d.ts delete mode 100644 airbyte-webapp/tsconfig.json delete mode 100644 airbyte-webapp/vite.config.ts delete mode 100644 airbyte-workers/Dockerfile delete mode 100644 airbyte-workers/README.md delete mode 100644 airbyte-workers/build.gradle delete mode 100644 airbyte-workers/gradle.properties delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/Application.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/ApplicationInitializer.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/JobStatus.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/OutputAndStatus.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/SyncException.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/ActivityBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/ApplicationBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/CloudStorageBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/ContainerOrchestratorConfigBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/DatabaseBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/JobErrorReportingBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/ProcessFactoryBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/SecretPersistenceBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/TemporalBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/config/WorkerConfigurationBeanFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/controller/HeartbeatController.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/run/TemporalWorkerRunFactory.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/run/WorkerRun.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/TemporalAttemptExecution.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/annotations/TemporalActivityStub.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/check/connection/CheckConnectionActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/check/connection/CheckConnectionActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/check/connection/CheckConnectionWorkflowImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/discover/catalog/DiscoverCatalogActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/discover/catalog/DiscoverCatalogActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/discover/catalog/DiscoverCatalogWorkflowImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/ConnectionManagerWorkflowImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/ConnectionNotificationWorkflowImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/ConnectionUpdaterWorkflowConfig.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/ManualSyncOutput.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/SyncCheckConnectionFailure.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/AutoDisableConnectionActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/AutoDisableConnectionActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/ConfigFetchActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/ConfigFetchActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/GenerateInputActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/GenerateInputActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/JobCreationAndStatusUpdateActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/JobCreationAndStatusUpdateActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/NotifySchemaChangeActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/NotifySchemaChangeActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/RecordMetricActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/RecordMetricActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/RouteToSyncTaskQueueActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/RouteToSyncTaskQueueActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/SlackConfigActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/SlackConfigActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/StreamResetActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/StreamResetActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/WorkflowConfigActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/scheduling/activities/WorkflowConfigActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/spec/SpecActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/spec/SpecActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/spec/SpecWorkflowImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/support/TemporalActivityStubGeneratorFunction.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/support/TemporalActivityStubInterceptor.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/support/TemporalProxyHelper.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/DbtTransformationActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/DbtTransformationActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/NormalizationActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/NormalizationActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/NormalizationSummaryCheckActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/NormalizationSummaryCheckActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/PersistStateActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/PersistStateActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/RefreshSchemaActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/RefreshSchemaActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/ReplicationActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/ReplicationActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/SyncOutputProvider.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/SyncWorkflowImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/WebhookOperationActivity.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/temporal/sync/WebhookOperationActivityImpl.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/tracing/StorageObjectGetInterceptor.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/tracing/TemporalSdkInterceptor.java delete mode 100644 airbyte-workers/src/main/java/io/airbyte/workers/utils/ConfigReplacer.java delete mode 100644 airbyte-workers/src/main/resources/application-control-plane.yml delete mode 100644 airbyte-workers/src/main/resources/application.yml delete mode 100644 airbyte-workers/src/main/resources/micronaut-banner.txt delete mode 100644 airbyte-workers/src/test-integration/java/io/airbyte/workers/process/AsyncOrchestratorPodProcessIntegrationTest.java delete mode 100644 airbyte-workers/src/test-integration/java/io/airbyte/workers/process/KubePodProcessIntegrationTest.java delete mode 100644 airbyte-workers/src/test-integration/resources/application-test.yml delete mode 100644 airbyte-workers/src/test/java/io/airbyte/commons/temporal/scheduling/DefaultTaskQueueMapperTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/commons/temporal/scheduling/RouterServiceTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/general/DefaultCheckConnectionWorkerTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/general/DefaultDiscoverCatalogWorkerTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/general/DefaultGetSpecWorkerTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/run/TemporalWorkerRunFactoryTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/run/WorkerRunTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/StreamResetRecordsHelperTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/TemporalAttemptExecutionTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/check/connection/CheckConnectionWorkflowTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/ConnectionManagerWorkflowTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/ConnectionNotificationWorkflowTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/WorkflowReplayingTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/AutoDisableConnectionActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/ConfigFetchActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/GenerateInputActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/JobCreationAndStatusUpdateActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/NormalizationSummaryCheckActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/NotifySchemaChangeActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/RecordMetricActivityImplTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/RefreshSchemaActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/SlackConfigActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/StreamResetActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/activities/WorkflowConfigActivityImplTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/DbtFailureSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/EmptySyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/NormalizationFailureSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/NormalizationTraceFailureSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/PersistFailureSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/ReplicateFailureSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/SleepingSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/SourceAndDestinationFailureSyncWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/SyncWorkflowFailingOutputWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/SyncWorkflowFailingWithHearbeatTimeoutException.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/scheduling/testsyncworkflow/SyncWorkflowWithActivityFailureException.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/stubs/ErrorTestWorkflowImpl.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/stubs/InvalidTestWorkflowImpl.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/stubs/TestActivity.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/stubs/TestWorkflow.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/stubs/ValidTestWorkflowImpl.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/support/TemporalActivityStubInterceptorTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/support/TemporalProxyHelperTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/sync/NormalizationActivityImplTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/sync/PersistStateActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/sync/SyncWorkflowTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/temporal/sync/WebhookOperationActivityTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/tracing/DummySpan.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/tracing/StorageObjectGetInterceptorTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/tracing/TemporalSdkInterceptorTest.java delete mode 100644 airbyte-workers/src/test/java/io/airbyte/workers/utils/ConfigReplacerTest.java delete mode 100644 airbyte-workers/src/test/resources/Dockerfile.no_var delete mode 100644 airbyte-workers/src/test/resources/Dockerfile.with_var delete mode 100644 airbyte-workers/src/test/resources/airbyte_discovered_postgres_catalog_output.json delete mode 100644 airbyte-workers/src/test/resources/airbyte_postgres_catalog.json delete mode 100644 airbyte-workers/src/test/resources/checkWorkflowHistory.json delete mode 100644 airbyte-workers/src/test/resources/connectionManagerWorkflowHistory.json delete mode 100644 airbyte-workers/src/test/resources/simple_postgres_catalog_output.json delete mode 100644 airbyte-workers/src/test/resources/simple_postgres_full_table_sync_catalog.json delete mode 100644 airbyte-workers/src/test/resources/simple_postgres_init.sql delete mode 100644 airbyte-workers/src/test/resources/singer_discovered_postgres_catalog_output.json delete mode 100644 airbyte-workers/src/test/resources/singer_postgres_catalog.json delete mode 100644 airbyte-workers/src/test/resources/stripe_schema_message.json delete mode 100644 airbyte-workers/src/test/resources/syncWorkflowHistory.json delete mode 100644 airbyte-workers/src/test/resources/valid_spec.json delete mode 100644 charts/airbyte-bootloader/.gitignore delete mode 100644 charts/airbyte-bootloader/Chart.lock delete mode 100644 charts/airbyte-bootloader/Chart.yaml delete mode 100644 charts/airbyte-bootloader/README.md delete mode 100644 charts/airbyte-bootloader/templates/_helpers.tpl delete mode 100644 charts/airbyte-bootloader/templates/bootloader-secrets.yaml delete mode 100644 charts/airbyte-bootloader/templates/pod.yaml delete mode 100644 charts/airbyte-bootloader/values.yaml delete mode 100644 charts/airbyte-connector-builder-server/.gitignore delete mode 100644 charts/airbyte-connector-builder-server/Chart.lock delete mode 100644 charts/airbyte-connector-builder-server/Chart.yaml delete mode 100644 charts/airbyte-connector-builder-server/README.md delete mode 100644 charts/airbyte-connector-builder-server/templates/_helpers.tpl delete mode 100644 charts/airbyte-connector-builder-server/templates/deployment.yaml delete mode 100644 charts/airbyte-connector-builder-server/templates/secrets.yaml delete mode 100644 charts/airbyte-connector-builder-server/templates/service.yaml delete mode 100644 charts/airbyte-connector-builder-server/values.yaml delete mode 100644 charts/airbyte-cron/Chart.lock delete mode 100644 charts/airbyte-cron/Chart.yaml delete mode 100644 charts/airbyte-cron/README.md delete mode 100644 charts/airbyte-cron/templates/_helpers.tpl delete mode 100644 charts/airbyte-cron/templates/cron-secrets.yaml delete mode 100644 charts/airbyte-cron/templates/deployment.yaml delete mode 100644 charts/airbyte-cron/values.yaml delete mode 100644 charts/airbyte-metrics/.gitignore delete mode 100644 charts/airbyte-metrics/.helmignore delete mode 100644 charts/airbyte-metrics/Chart.lock delete mode 100644 charts/airbyte-metrics/Chart.yaml delete mode 100644 charts/airbyte-metrics/README.md delete mode 100644 charts/airbyte-metrics/templates/_helpers.tpl delete mode 100644 charts/airbyte-metrics/templates/deployment.yaml delete mode 100644 charts/airbyte-metrics/values.yaml delete mode 100644 charts/airbyte-pod-sweeper/.gitignore delete mode 100644 charts/airbyte-pod-sweeper/Chart.lock delete mode 100644 charts/airbyte-pod-sweeper/Chart.yaml delete mode 100644 charts/airbyte-pod-sweeper/README.md delete mode 100644 charts/airbyte-pod-sweeper/templates/_helpers.tpl delete mode 100644 charts/airbyte-pod-sweeper/templates/configmap.yaml delete mode 100644 charts/airbyte-pod-sweeper/templates/deployment.yaml delete mode 100644 charts/airbyte-pod-sweeper/values.yaml delete mode 100644 charts/airbyte-server/.gitignore delete mode 100644 charts/airbyte-server/Chart.lock delete mode 100644 charts/airbyte-server/Chart.yaml delete mode 100644 charts/airbyte-server/README.md delete mode 100644 charts/airbyte-server/templates/_helpers.tpl delete mode 100644 charts/airbyte-server/templates/deployment.yaml delete mode 100644 charts/airbyte-server/templates/secrets.yaml delete mode 100644 charts/airbyte-server/templates/service.yaml delete mode 100644 charts/airbyte-server/values.yaml delete mode 100644 charts/airbyte-temporal/.gitignore delete mode 100644 charts/airbyte-temporal/Chart.lock delete mode 100644 charts/airbyte-temporal/Chart.yaml delete mode 100644 charts/airbyte-temporal/README.md delete mode 100644 charts/airbyte-temporal/templates/_helpers.tpl delete mode 100644 charts/airbyte-temporal/templates/configmap.yaml delete mode 100644 charts/airbyte-temporal/templates/deployment.yaml delete mode 100644 charts/airbyte-temporal/templates/secrets.yaml delete mode 100644 charts/airbyte-temporal/templates/service.yaml delete mode 100644 charts/airbyte-temporal/values.yaml delete mode 100644 charts/airbyte-webapp/.gitignore delete mode 100644 charts/airbyte-webapp/Chart.lock delete mode 100644 charts/airbyte-webapp/Chart.yaml delete mode 100644 charts/airbyte-webapp/README.md delete mode 100644 charts/airbyte-webapp/templates/_helpers.tpl delete mode 100644 charts/airbyte-webapp/templates/deployment.yaml delete mode 100644 charts/airbyte-webapp/templates/ingress.yaml delete mode 100644 charts/airbyte-webapp/templates/secrets.yaml delete mode 100644 charts/airbyte-webapp/templates/service.yaml delete mode 100644 charts/airbyte-webapp/values.yaml delete mode 100644 charts/airbyte-worker/.gitignore delete mode 100644 charts/airbyte-worker/Chart.lock delete mode 100644 charts/airbyte-worker/Chart.yaml delete mode 100644 charts/airbyte-worker/README.md delete mode 100644 charts/airbyte-worker/templates/_helpers.tpl delete mode 100644 charts/airbyte-worker/templates/deployment.yaml delete mode 100644 charts/airbyte-worker/templates/secrets.yaml delete mode 100644 charts/airbyte-worker/values.yaml delete mode 100644 charts/airbyte/.gitignore delete mode 100644 charts/airbyte/.helmignore delete mode 100644 charts/airbyte/Chart.lock delete mode 100644 charts/airbyte/Chart.yaml delete mode 100644 charts/airbyte/Chart.yaml.test delete mode 100644 charts/airbyte/README.md delete mode 100755 charts/airbyte/ci.sh delete mode 100644 charts/airbyte/templates/NOTES.txt delete mode 100644 charts/airbyte/templates/_helpers.tpl delete mode 100644 charts/airbyte/templates/airbyte-db.yaml delete mode 100644 charts/airbyte/templates/env-configmap.yaml delete mode 100644 charts/airbyte/templates/gcs-log-creds-secret.yaml delete mode 100644 charts/airbyte/templates/minio.yaml delete mode 100644 charts/airbyte/templates/secret.yaml delete mode 100644 charts/airbyte/templates/serviceaccount.yaml delete mode 100644 charts/airbyte/templates/tests/test-webapp.yaml delete mode 100644 charts/airbyte/values.yaml delete mode 100644 charts/airbyte/values.yaml.test delete mode 100644 docker-compose-cloud.buildx.yaml delete mode 100644 docker-compose.acceptance-test.yaml delete mode 100644 docker-compose.build.yaml delete mode 100644 docker-compose.datadog.yaml delete mode 100644 docker-compose.debug.yaml delete mode 100644 docker-compose.yaml delete mode 100644 flags.yml delete mode 100644 temporal/dynamicconfig/development.yaml delete mode 100644 terraform/README.md delete mode 100644 terraform/aws/demo/core/init.sh delete mode 100644 terraform/aws/demo/core/main.tf delete mode 100644 terraform/aws/demo/core/outputs.tf delete mode 100644 terraform/aws/demo/core/variables.tf delete mode 100644 terraform/aws/demo/lb/auth.html delete mode 100644 terraform/aws/demo/lb/main.tf delete mode 100644 terraform/aws/demo/lb/variables.tf delete mode 100644 terraform/aws/demo/main.tf delete mode 100644 terraform/aws/demo/terraform.tf delete mode 100644 terraform/aws/demo/variables.tf diff --git a/.env b/.env deleted file mode 100644 index 7279aca5d7fc7..0000000000000 --- a/.env +++ /dev/null @@ -1,117 +0,0 @@ -# This file only contains Docker relevant variables. -# -# Variables with defaults have been omitted to avoid duplication of defaults. -# The only exception to the non-default rule are env vars related to scaling. -# -# See https://github.com/airbytehq/airbyte/blob/master/airbyte-config/config-models/src/main/java/io/airbyte/config/Configs.java -# for the latest environment variables. -# -# # Contributors - please organise this env file according to the above linked file. - - -### SHARED ### -VERSION=0.40.32 - -# When using the airbyte-db via default docker image -CONFIG_ROOT=/data -DATA_DOCKER_MOUNT=airbyte_data -DB_DOCKER_MOUNT=airbyte_db - -# Workspace storage for running jobs (logs, etc) -WORKSPACE_ROOT=/tmp/workspace -WORKSPACE_DOCKER_MOUNT=airbyte_workspace - -# Local mount to access local files from filesystem -# todo (cgardens) - when we are mount raw directories instead of named volumes, *_DOCKER_MOUNT must -# be the same as *_ROOT. -# Issue: https://github.com/airbytehq/airbyte/issues/578 -LOCAL_ROOT=/tmp/airbyte_local -LOCAL_DOCKER_MOUNT=/tmp/airbyte_local -# todo (cgardens) - hack to handle behavior change in docker compose. *_PARENT directories MUST -# already exist on the host filesystem and MUST be parents of *_ROOT. -# Issue: https://github.com/airbytehq/airbyte/issues/577 -HACK_LOCAL_ROOT_PARENT=/tmp - -# Proxy Configuration -# Set to empty values, e.g. "" to disable basic auth -BASIC_AUTH_USERNAME=airbyte -BASIC_AUTH_PASSWORD=password -BASIC_AUTH_PROXY_TIMEOUT=600 - -### DATABASE ### -# Airbyte Internal Job Database, see https://docs.airbyte.io/operator-guides/configuring-airbyte-db -DATABASE_USER=docker -DATABASE_PASSWORD=docker -DATABASE_HOST=db -DATABASE_PORT=5432 -DATABASE_DB=airbyte -# translate manually DATABASE_URL=jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_DB} (do not include the username or password here) -DATABASE_URL=jdbc:postgresql://db:5432/airbyte -JOBS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.40.26.001 - -# Airbyte Internal Config Database, defaults to Job Database if empty. Explicitly left empty to mute docker compose warnings. -CONFIG_DATABASE_USER= -CONFIG_DATABASE_PASSWORD= -CONFIG_DATABASE_URL= -CONFIGS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.40.23.002 - -### AIRBYTE SERVICES ### -TEMPORAL_HOST=airbyte-temporal:7233 -INTERNAL_API_HOST=airbyte-server:8001 -CONNECTOR_BUILDER_API_HOST=airbyte-connector-builder-server:80 -WEBAPP_URL=http://localhost:8000/ -# Although not present as an env var, required for webapp configuration. -API_URL=/api/v1/ -CONNECTOR_BUILDER_API_URL=/connector-builder-api - -### JOBS ### -# Relevant to scaling. -SYNC_JOB_MAX_ATTEMPTS=3 -SYNC_JOB_MAX_TIMEOUT_DAYS=3 -JOB_MAIN_CONTAINER_CPU_REQUEST= -JOB_MAIN_CONTAINER_CPU_LIMIT= -JOB_MAIN_CONTAINER_MEMORY_REQUEST= -JOB_MAIN_CONTAINER_MEMORY_LIMIT= - -NORMALIZATION_JOB_MAIN_CONTAINER_MEMORY_LIMIT= -NORMALIZATION_JOB_MAIN_CONTAINER_MEMORY_REQUEST= -NORMALIZATION_JOB_MAIN_CONTAINER_CPU_LIMIT= -NORMALIZATION_JOB_MAIN_CONTAINER_CPU_REQUEST= - -### LOGGING/MONITORING/TRACKING ### -TRACKING_STRATEGY=segment -JOB_ERROR_REPORTING_STRATEGY=logging -# Although not present as an env var, expected by Log4J configuration. -LOG_LEVEL=INFO - - -### APPLICATIONS ### -# Worker # -WORKERS_MICRONAUT_ENVIRONMENTS=control-plane -# Cron # -CRON_MICRONAUT_ENVIRONMENTS=control-plane -# Relevant to scaling. -MAX_SYNC_WORKERS=5 -MAX_SPEC_WORKERS=5 -MAX_CHECK_WORKERS=5 -MAX_DISCOVER_WORKERS=5 -MAX_NOTIFY_WORKERS=5 -SHOULD_RUN_NOTIFY_WORKFLOWS=false -# Temporal Activity configuration -ACTIVITY_MAX_ATTEMPT= -ACTIVITY_INITIAL_DELAY_BETWEEN_ATTEMPTS_SECONDS= -ACTIVITY_MAX_DELAY_BETWEEN_ATTEMPTS_SECONDS= -WORKFLOW_FAILURE_RESTART_DELAY_SECONDS= - -### FEATURE FLAGS ### -AUTO_DISABLE_FAILING_CONNECTIONS=false -FORCE_MIGRATE_SECRET_STORE=false - -### MONITORING FLAGS ### -# Accepted values are datadog and otel (open telemetry) -METRIC_CLIENT= -# Useful only when metric client is set to be otel. Must start with http:// or https://. -OTEL_COLLECTOR_ENDPOINT="http://host.docker.internal:4317" - -USE_STREAM_CAPABLE_STATE=true -AUTO_DETECT_SCHEMA=true diff --git a/.env.dev b/.env.dev deleted file mode 100644 index 19480e7072f9a..0000000000000 --- a/.env.dev +++ /dev/null @@ -1,38 +0,0 @@ -# For internal Airbyte dev use. - -VERSION=dev -DATABASE_USER=docker -DATABASE_PASSWORD=docker -DATABASE_DB=airbyte -DATABASE_URL=jdbc:postgresql://db:5432/airbyte -CONFIG_ROOT=/data -WORKSPACE_ROOT=/tmp/workspace -DATA_DOCKER_MOUNT=airbyte_data_dev -DB_DOCKER_MOUNT=airbyte_db_dev -WORKSPACE_DOCKER_MOUNT=airbyte_workspace_dev -# todo (cgardens) - when we are mount raw directories instead of named volumes, *_DOCKER_MOUNT must -# be the same as *_ROOT. -# Issue: https://github.com/airbytehq/airbyte/issues/578 -LOCAL_ROOT=/tmp/airbyte_local_dev -LOCAL_DOCKER_MOUNT=/tmp/airbyte_local_dev -TRACKING_STRATEGY=logging -# todo (cgardens) - hack to handle behavior change in docker compose. *_PARENT directories MUST -# already exist on the host filesystem and MUST be parents of *_ROOT. -# Issue: https://github.com/airbytehq/airbyte/issues/577 -HACK_LOCAL_ROOT_PARENT=/tmp -WEBAPP_URL=http://localhost:8000/ -API_URL=/api/v1/ -INTERNAL_API_HOST=airbyte-server:8001 -CONNECTOR_BUILDER_API_HOST=airbyte-connector-builder-server:80 -SYNC_JOB_MAX_ATTEMPTS=3 -SYNC_JOB_MAX_TIMEOUT_DAYS=3 -WORKERS_MICRONAUT_ENVIRONMENTS=control-plane -CRON_MICRONAUT_ENVIRONMENTS=control-plane -AUTO_DETECT_SCHEMA=true - -# Sentry -SENTRY_DSN="" - -# Migration Configuration -CONFIGS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.35.15.001 -JOBS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.29.15.001 diff --git a/.github/actions/build-and-push-branch/action.yml b/.github/actions/build-and-push-branch/action.yml deleted file mode 100644 index f26e9495543a7..0000000000000 --- a/.github/actions/build-and-push-branch/action.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: "Build OSS Branch and Push Minimum Required OSS Images" -description: "Build jars and docker images tagged for a particular branch. Primarily used for running OSS branch code in Cloud." -inputs: - branch_version_tag: - description: 'Used to tag jars and docker images with a branch-specific version (should use the form "dev-" to pass AirbyteVersion validation)' - required: false - dockerhub_username: - description: "Used to log in to dockerhub for pushing images" - required: true - dockerhub_token: - description: "Used to log in to dockerhub for pushing images" - required: true -runs: - using: "composite" - steps: - - name: Build - id: build - uses: ./.github/actions/build-branch - with: - branch_version_tag: ${{ inputs.branch_version_tag }} - - - name: Login to Docker (on Master) - uses: docker/login-action@v2 - with: - username: ${{ inputs.dockerhub_username }} - password: ${{ inputs.dockerhub_token }} - - - name: Push Docker Images - run: | - GIT_REVISION=$(git rev-parse HEAD) - [ [ -z "$GIT_REVISION" ] ] && echo "Couldn't get the git revision..." && exit 1 - VERSION=${{ steps.build.outputs.branch_version_tag }} GIT_REVISION=$GIT_REVISION docker compose -f docker-compose-cloud.buildx.yaml push - shell: bash diff --git a/.github/actions/build-branch/action.yml b/.github/actions/build-branch/action.yml deleted file mode 100644 index 1f27e6c478b1b..0000000000000 --- a/.github/actions/build-branch/action.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: "Build OSS Branch" -description: "Build jars and docker images tagged for a particular branch. Primarily used for running OSS branch code in Cloud." -inputs: - branch_version_tag: - description: 'Used to tag jars and docker images with a branch-specific version (should use the form "dev-" to pass AirbyteVersion validation)' - required: false - build_docker_images: - description: 'Build docker images' - default: 'true' - required: false -outputs: - branch_version_tag: - description: "Tag used for jars and docker images. Either user specified or auto generated as `dev-`" - value: ${{ steps.parse-input.outputs.branch_version_tag }} -runs: - using: "composite" - steps: - - name: "Parse Input" - id: parse-input - shell: bash - run: |- - # if the *branch_version_tag* input param is not specified, then generate it as 'dev-` - # - [[ "${{ inputs.branch_version_tag }}" != '' ]] && echo "branch_version_tag=${{ inputs.branch_version_tag }}" >> $GITHUB_OUTPUT \ - || { short_hash=$(git rev-parse --short=10 HEAD); echo "branch_version_tag=dev-$short_hash" >> $GITHUB_OUTPUT ; } - - - name: Prepare Runner for Building - uses: ./.github/actions/runner-prepare-for-build - - - name: Build with Docker Images - if: inputs.build_docker_images == 'true' - run: VERSION=${{ steps.parse-input.outputs.branch_version_tag }} SUB_BUILD=PLATFORM ./gradlew build --scan - shell: bash - - - name: Build without Docker Images - if: inputs.build_docker_images != 'true' - run: VERSION=${{ steps.parse-input.outputs.branch_version_tag }} SUB_BUILD=PLATFORM ./gradlew test --scan - shell: bash - - - name: Publish to Maven Local - run: VERSION=${{ steps.parse-input.outputs.branch_version_tag }} SUB_BUILD=PLATFORM ./gradlew publishToMavenLocal - shell: bash diff --git a/.github/workflows/build-report.yml b/.github/workflows/build-report.yml index 4cdd45eaaabd4..9f662ddd58549 100644 --- a/.github/workflows/build-report.yml +++ b/.github/workflows/build-report.yml @@ -15,7 +15,6 @@ jobs: timeout-minutes: 5 runs-on: ubuntu-latest if: github.ref == 'refs/heads/master' - environment: more-secrets steps: - name: Checkout Airbyte uses: actions/checkout@v3 diff --git a/.github/workflows/doc-link-check.yml b/.github/workflows/doc-link-check.yml index 0d3626150cfc6..8e4980b5dc4d5 100644 --- a/.github/workflows/doc-link-check.yml +++ b/.github/workflows/doc-link-check.yml @@ -12,7 +12,6 @@ jobs: markdown-link-check: timeout-minutes: 50 runs-on: ubuntu-latest - environment: more-secrets steps: - uses: actions/checkout@master # check all files on master diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index a1c63f5f4b623..31b07166dc6c7 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,4 +1,4 @@ -name: Airbyte CI +name: Airbyte Connectors & Octavia CI env: S3_BUILD_CACHE_ACCESS_KEY_ID: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} @@ -80,12 +80,6 @@ jobs: - 'airbyte-commons-worker/**' db: - 'airbyte-db/**' - frontend: - - 'airbyte-api/src/main/openapi/config.yaml' - - 'airbyte-connector-builder-server/CDK_VERSION' - - 'airbyte-connector-builder-server/src/main/openapi/openapi.yaml' - - 'airbyte-webapp/**' - - 'airbyte-webapp-e2e-tests/**' # Uncomment to debug. # changes-output: @@ -155,13 +149,6 @@ jobs: attempt_limit: 3 attempt_delay: 5000 # in ms - - name: Build Platform Docker Images - uses: Wandalen/wretry.action@master - with: - command: SUB_BUILD=PLATFORM ./gradlew --no-daemon assemble --scan - attempt_limit: 3 - attempt_delay: 5000 # in ms - - name: Run integration tests uses: Wandalen/wretry.action@master with: @@ -350,728 +337,12 @@ jobs: label: ${{ needs.start-connectors-base-build-runner.outputs.label }} ec2-instance-id: ${{ needs.start-connectors-base-build-runner.outputs.ec2-instance-id }} - ## Frontend Test - # In case of self-hosted EC2 errors, remove this block. - start-frontend-runner: - name: "Frontend: Start EC2 Runner" - needs: - - changes - # Because scheduled builds on master require us to skip the changes job. Use always() to force this to run on master. - if: | - needs.changes.outputs.frontend == 'true' || needs.changes.outputs.build == 'true' || github.ref == 'refs/heads/master' - || (always() && needs.changes.outputs.backend == 'true') - timeout-minutes: 10 - runs-on: ubuntu-latest - outputs: - label: ${{ steps.start-ec2-runner.outputs.label }} - ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Start AWS Runner - id: start-ec2-runner - uses: ./.github/actions/start-aws-runner - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - github-token: ${{ env.PAT }} - frontend-build: - name: "Frontend: Build" - needs: - - start-frontend-runner - runs-on: ${{ needs.start-frontend-runner.outputs.label }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - # We need to fetch at least one more commmit for the Chromatic action not to fail - # but since we don't do screenshot comparison we don't need to fetch the full history. - with: - fetch-depth: 2 - - - name: Cache Build Artifacts - uses: ./.github/actions/cache-build-artifacts - with: - cache-key: ${{ secrets.CACHE_VERSION }} - cache-python: "false" - - - uses: actions/setup-java@v3 - with: - distribution: "zulu" - java-version: "17" - - - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - - name: Set up CI Gradle Properties - run: | - mkdir -p ~/.gradle/ - cat > ~/.gradle/gradle.properties < ~/.gradle/gradle.properties < ~/.gradle/gradle.properties < ~/.gradle/gradle.properties <> $GITHUB_OUTPUT - - release-chart: - name: Chart release - runs-on: ubuntu-22.04 - needs: ["generate-semantic-version"] - permissions: write-all - steps: - - uses: actions/checkout@v3 - with: - path: "airbyte" - fetch-depth: 0 - - - uses: actions/checkout@v3 - with: - repository: "airbytehq/helm-charts" - token: ${{ secrets.GH_PAT_MAINTENANCE_OSS }} - path: "airbyte-oss" - - - name: Replace semantic version in main chart for deps - shell: bash - working-directory: ./airbyte/charts - run: | - sed -i -E "s/ version: [[:digit:]].[[:digit:]].[[:digit:]]/ version: ${{ needs.generate-semantic-version.outputs.next-version }}/g" airbyte/Chart.yaml - sed -i -E 's/version: [0-9]+\.[0-9]+\.[0-9]+/version: ${{ needs.generate-semantic-version.outputs.next-version }}/' airbyte/Chart.yaml - - - name: "Helm package" - shell: bash - run: | - declare -a StringArray=("airbyte-bootloader" "airbyte-server" "airbyte-temporal" "airbyte-webapp" "airbyte-pod-sweeper" "airbyte-worker" "airbyte-metrics" "airbyte-cron" "airbyte-connector-builder-server") - for val in ${StringArray[@]}; do - cd ./airbyte/charts/${val} && helm dep update && cd $GITHUB_WORKSPACE - sed -i -E 's/version: \"[0-9]+\.[0-9]+\.[0-9]+\"/version: \"${{ needs.generate-semantic-version.outputs.next-version }}\"/' ./airbyte/charts/${val}/Chart.yaml - helm package ./airbyte/charts/${val} -d airbyte-oss --version ${{ needs.generate-semantic-version.outputs.next-version }} - done - helm repo index airbyte-oss/ - - - name: Commit and push changes - uses: EndBug/add-and-commit@v9 - with: - message: "Bump release to ${{ needs.generate-semantic-version.outputs.next-version }}" - add: "." - cwd: "./airbyte-oss/" - - - name: "Helm package main chart" - shell: bash - run: | - echo "Waiting for published charts to be synced in helm-charts repo" - sleep 300 - declare -a StringArray=("airbyte") - for val in ${StringArray[@]}; do - cd ./airbyte/charts/${val} && cat Chart.yaml && helm dep update && cd $GITHUB_WORKSPACE - helm package ./airbyte/charts/${val} -d airbyte-oss --version ${{ needs.generate-semantic-version.outputs.next-version }} - done - helm repo index airbyte-oss/ - - - name: Commit and push changes - uses: EndBug/add-and-commit@v9 - with: - message: "Bump release to ${{ needs.generate-semantic-version.outputs.next-version }}" - add: "." - cwd: "./airbyte-oss/" - - - name: "Generate changelog" - shell: bash - id: changelog - run: | - cd ./airbyte/ - changelog=$(PAGER=cat git log $(git describe --tags --match "*-helm" $(git rev-list --tags --max-count=1))..HEAD --oneline --decorate=no) - echo "changelog<> $GITHUB_ENV - echo "$changelog" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 - with: - path: ./airbyte/ - branch: update-helm-chart-version-ref - branch-suffix: random - title: Bump helm chart version reference to ${{ needs.generate-semantic-version.outputs.next-version }} - body: | - ## What - Bump version reference in all Chart.yaml files to ${{ needs.generate-semantic-version.outputs.next-version }} - CHANGELOG: - ${{ env.changelog }} - commit-message: Bump helm chart version reference to ${{ needs.generate-semantic-version.outputs.next-version }} - delete-branch: true - - - name: Create tag - shell: bash - run: | - cd ./airbyte/ - git tag ${{ needs.generate-semantic-version.outputs.tag }} - git push origin ${{ needs.generate-semantic-version.outputs.tag }} diff --git a/.github/workflows/publish-oss-for-cloud.yml b/.github/workflows/publish-oss-for-cloud.yml deleted file mode 100644 index fda551da9f3e4..0000000000000 --- a/.github/workflows/publish-oss-for-cloud.yml +++ /dev/null @@ -1,190 +0,0 @@ -name: Publish OSS Artifacts for Cloud - -env: - # enable gradle remote build cache - S3_BUILD_CACHE_ACCESS_KEY_ID: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - S3_BUILD_CACHE_SECRET_KEY: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - -on: - workflow_dispatch: - inputs: - oss_ref: - description: "Publish artifacts for the following git ref (if unspecified, uses the latest commit for the current branch):" - required: false -jobs: - start-runner: - name: "Start Runner on AWS" - timeout-minutes: 10 - runs-on: ubuntu-latest - outputs: - label: ${{ steps.start-ec2-runner.outputs.label }} - ec2-instance-id: ${{ steps.start-ec2-runner.outputs.ec2-instance-id }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Start AWS Runner - id: start-ec2-runner - uses: ./.github/actions/start-aws-runner - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - github-token: ${{ env.PAT }} - - generate-tags: - name: "Generate Dev and Master Tags" - runs-on: ubuntu-latest - outputs: - dev_tag: ${{ steps.set-outputs.outputs.dev_tag }} - master_tag: ${{ steps.set-outputs.outputs.master_tag }} - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - ref: ${{ github.event.inputs.oss_ref || github.ref }} - - name: Generate Outputs - id: set-outputs - shell: bash - run: |- - set -x - - commit_sha=$(git rev-parse --short=10 HEAD) - - # set dev_tag - # AirbyteVersion.java allows versions that have a prefix of 'dev' - echo "dev_tag=dev-${commit_sha}" >> $GITHUB_OUTPUT - - # If this commit is on the master branch, also set master_tag - if $(git merge-base --is-ancestor "${commit_sha}" master); then - echo "master_tag=${commit_sha}" >> $GITHUB_OUTPUT - fi - cat $GITHUB_OUTPUT || true # for the sake of investigation - - oss-branch-build: - concurrency: - # only allow one workflow run at a time for a given SHA - # to prevent multiple runs from pushing artifacts for the same SHA at the same time - # note: using inputs in the group expression only works when specifying concurrency at the job level - group: ${{ github.workflow }}-${{ inputs.oss_ref || github.sha }} - cancel-in-progress: false - name: "Gradle Build and Publish" - needs: - - start-runner - - generate-tags - runs-on: ${{ needs.start-runner.outputs.label }} - environment: more-secrets - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - ref: ${{ github.event.inputs.oss_ref || github.ref }} - - - name: Build Branch - uses: ./.github/actions/build-branch - with: - branch_version_tag: ${{ needs.generate-tags.outputs.dev_tag }} - build_docker_images: 'false' - - - name: Publish Dev Jars - env: - CLOUDREPO_USER: ${{ secrets.CLOUDREPO_USER }} - CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_PASSWORD }} - run: VERSION=${{ needs.generate-tags.outputs.dev_tag }} SUB_BUILD=PLATFORM ./gradlew publish - shell: bash - - - name: Publish Master Jars - if: needs.generate-tags.outputs.master_tag != '' - env: - CLOUDREPO_USER: ${{ secrets.CLOUDREPO_USER }} - CLOUDREPO_PASSWORD: ${{ secrets.CLOUDREPO_PASSWORD }} - run: VERSION=${{ needs.generate-tags.outputs.master_tag }} SUB_BUILD=PLATFORM ./gradlew publish - shell: bash - - docker-push: - concurrency: - # only allow one workflow run at a time for a given SHA - # to prevent multiple runs from pushing artifacts for the same SHA at the same time - # note: using inputs in the group expression only works when specifying concurrency at the job level - group: ${{ github.workflow }}-${{ inputs.oss_ref || github.sha }} - cancel-in-progress: false - name: "Push Docker Images" - needs: - - start-runner - - generate-tags - - oss-branch-build - runs-on: ${{ needs.start-runner.outputs.label }} - steps: - - name: Login to Docker (on Master) - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_PASSWORD }} - - - name: Prepare Docker buildx - run: | - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - docker buildx create --name oss-buildx --driver docker-container --use - shell: bash - - - name: Set Git Revision - run: | - GIT_REVISION=$(git rev-parse HEAD) - [ [ -z "$GIT_REVISION" ] ] && echo "Couldn't get the git revision..." && exit 1 - echo "GIT_REVISION=${GIT_REVISION}" >> $GITHUB_ENV - shell: bash - - - name: Prepare Runner for Building - uses: ./.github/actions/runner-prepare-for-build - - # Put tars/artifacts in the correct build directories so docker buildx can find the artifacts it needs when building docker images - - name: Prepare Docker context - run: VERSION=${{ needs.generate-tags.outputs.dev_tag }} SUB_BUILD=PLATFORM ./gradlew copyGeneratedTar airbyte-db:db-lib:copyInitSql - shell: bash - - # Build docker images using docker buildx (for multi platform) - - name: Push Docker Images - env: - VERSION: ${{ needs.generate-tags.outputs.dev_tag }} - ALT_TAG: ${{ needs.generate-tags.outputs.master_tag }} - run: GIT_REVISION=$GIT_REVISION docker buildx bake -f docker-compose-cloud.buildx.yaml --push - shell: bash - - - name: Cleanup Docker buildx - run: docker buildx rm oss-buildx - shell: bash - - stop-runner: - name: "Stop Build EC2 Runner" - timeout-minutes: 10 - needs: - - start-runner # required to get output from the start-runner job - - docker-push # wait until all publish steps are done - runs-on: ubuntu-latest - # Always is required to stop the runner even if the previous job has errors. However always() runs even if the previous step is skipped. - # Thus, we check for skipped here. - if: ${{ always() && needs.start-runner.result != 'skipped'}} - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.SELF_RUNNER_AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.SELF_RUNNER_AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-2 - - name: Checkout Airbyte - uses: actions/checkout@v3 - - name: Check PAT rate limits - run: | - ./tools/bin/find_non_rate_limited_PAT \ - ${{ secrets.GH_PAT_BUILD_RUNNER_OSS }} \ - ${{ secrets.GH_PAT_BUILD_RUNNER_BACKUP }} - - name: Stop EC2 runner - uses: airbytehq/ec2-github-runner@base64v1.1.0 - with: - mode: stop - github-token: ${{ env.PAT }} - label: ${{ needs.start-runner.outputs.label }} - ec2-instance-id: ${{ needs.start-runner.outputs.ec2-instance-id }} diff --git a/.github/workflows/release-airbyte-os.yml b/.github/workflows/release-airbyte-os.yml index 461b87cb41cc2..0d1d33cd0f888 100644 --- a/.github/workflows/release-airbyte-os.yml +++ b/.github/workflows/release-airbyte-os.yml @@ -1,6 +1,10 @@ name: Release Open Source Airbyte concurrency: release-airbyte + +# TODO: If we continue to use this action from here it needs to be updated to point to airbyte-platform +# where appropriate + on: workflow_dispatch: inputs: @@ -37,7 +41,6 @@ jobs: # In case of self-hosted EC2 errors, removed the `needs` line and switch back to running on ubuntu-latest. needs: start-release-airbyte-runner # required to start the main job when the runner is ready runs-on: ${{ needs.start-release-airbyte-runner.outputs.label }} # run the job on the newly created runner - environment: more-secrets steps: - name: Checkout uses: actions/checkout@v3 @@ -71,7 +74,6 @@ jobs: # - The self hosted runner used in releaseAirbyte does not have the docker buildx command to build multi-arch images releaseOctavia: runs-on: ubuntu-latest - environment: more-secrets steps: - name: Checkout uses: actions/checkout@v3 @@ -98,7 +100,6 @@ jobs: - releaseAirbyte - releaseOctavia runs-on: ubuntu-latest - environment: more-secrets steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/run-performance-test.yml b/.github/workflows/run-performance-test.yml deleted file mode 100644 index 929df1102cca7..0000000000000 --- a/.github/workflows/run-performance-test.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Run Performance Test -on: - workflow_dispatch: - inputs: - repo: - description: "Repo to check out code from. Defaults to the main airbyte repo. Set this when building connectors from forked repos." - required: false - default: "airbytehq/airbyte" - gitref: - description: "The git ref to check out from the specified repository." - required: false - default: master - test-name: - description: "Test to run classname" - required: true - -jobs: - single-test-runner: - timeout-minutes: 300 - needs: start-platform-build-runner # required to start the main job when the runner is ready - runs-on: ${{ needs.start-platform-build-runner.outputs.label }} # run the job on the newly created runner - environment: more-secrets - steps: - - name: Checkout Airbyte - uses: actions/checkout@v3 - with: - repository: ${{ github.event.inputs.repo }} - ref: ${{ github.event.inputs.gitref }} - - - name: Npm Caching - uses: actions/cache@v3 - with: - path: | - ~/.npm - key: ${{ secrets.CACHE_VERSION }}-npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ secrets.CACHE_VERSION }}-npm-${{ runner.os }}- - - # this intentionally does not use restore-keys so we don't mess with gradle caching - - name: Gradle Caching - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - **/.venv - key: ${{ secrets.CACHE_VERSION }}-${{ runner.os }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/package-lock.json') }} - - - uses: actions/setup-java@v3 - with: - distribution: "zulu" - java-version: "14" - - - name: Build - id: run-specific-test - run: ./gradlew allTest --tests *${{ github.event.inputs.test-name }} diff --git a/.github/workflows/test-command.yml b/.github/workflows/test-command.yml index 11f2214d9b83c..0bcf8f49ee3fd 100644 --- a/.github/workflows/test-command.yml +++ b/.github/workflows/test-command.yml @@ -58,7 +58,6 @@ jobs: timeout-minutes: 240 needs: start-test-runner runs-on: ${{ needs.start-test-runner.outputs.label }} - environment: more-secrets steps: - name: Link comment to workflow run if: github.event.inputs.comment-id diff --git a/.github/workflows/test-performance-command.yml b/.github/workflows/test-performance-command.yml index b8c1a040d3704..703be55140e1d 100644 --- a/.github/workflows/test-performance-command.yml +++ b/.github/workflows/test-performance-command.yml @@ -1,6 +1,6 @@ # runs ./tools/bin/ci_performance_test.sh # which is more or less ./gradlew performanceTest limited to connectors with changes -name: Run Performance Test +name: Run Connectors Performance Test on: workflow_dispatch: inputs: @@ -57,7 +57,6 @@ jobs: timeout-minutes: 240 needs: start-test-runner runs-on: ${{ needs.start-test-runner.outputs.label }} - environment: more-secrets steps: - name: Search for valid connector name format id: regex diff --git a/airbyte-bootloader/Dockerfile b/airbyte-bootloader/Dockerfile deleted file mode 100644 index 06e50598ed7ab..0000000000000 --- a/airbyte-bootloader/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -ARG JDK_IMAGE=airbyte/airbyte-base-java-image:1.0 -FROM ${JDK_IMAGE} - -ARG VERSION=0.40.32 - -ENV APPLICATION airbyte-bootloader -ENV VERSION ${VERSION} - -WORKDIR /app - -ADD bin/${APPLICATION}-${VERSION}.tar /app - - -ENTRYPOINT ["/bin/bash", "-c", "${APPLICATION}-${VERSION}/bin/${APPLICATION}"] diff --git a/airbyte-bootloader/Readme.md b/airbyte-bootloader/Readme.md deleted file mode 100644 index 831613918da99..0000000000000 --- a/airbyte-bootloader/Readme.md +++ /dev/null @@ -1,6 +0,0 @@ -# airbyte-bootloader - -This application runs at start up for Airbyte. It is responsible for making sure that the environment is upgraded and in a good state. e.g. It makes sure the database has been migrated to the correct version. - -## Entrypoint -* Application.java - has the main method for running the bootloader. diff --git a/airbyte-bootloader/build.gradle b/airbyte-bootloader/build.gradle deleted file mode 100644 index d61eaedd6be16..0000000000000 --- a/airbyte-bootloader/build.gradle +++ /dev/null @@ -1,76 +0,0 @@ -plugins { - id 'application' -} - -dependencies { - annotationProcessor platform(libs.micronaut.bom) - annotationProcessor libs.bundles.micronaut.annotation.processor - - implementation platform(libs.micronaut.bom) - implementation libs.bundles.micronaut - - // Ensure that the versions defined in deps.toml are used - // instead of versions from transitive dependencies - implementation (libs.flyway.core) { - force = true - } - implementation (libs.jooq) { - force = true - } - - implementation project(':airbyte-config:init') - implementation project(':airbyte-config:config-models') - implementation project(':airbyte-config:config-persistence') - implementation project(':airbyte-db:db-lib') - implementation project(":airbyte-json-validation") - implementation libs.airbyte.protocol - implementation project(':airbyte-persistence:job-persistence') - - testAnnotationProcessor platform(libs.micronaut.bom) - testAnnotationProcessor libs.bundles.micronaut.test.annotation.processor - - testImplementation libs.bundles.micronaut.test - testImplementation libs.bundles.junit - testImplementation libs.junit.jupiter.system.stubs - testImplementation libs.platform.testcontainers.postgresql -} - -mainClassName = 'io.airbyte.bootloader.Application' - -application { - applicationName = project.name - mainClass = mainClassName - applicationDefaultJvmArgs = ['-XX:+ExitOnOutOfMemoryError', '-XX:MaxRAMPercentage=75.0'] -} - -Properties env = new Properties() -rootProject.file('.env.dev').withInputStream { env.load(it) } - -run { - // default for running on local machine. - env.each { entry -> - environment entry.getKey(), entry.getValue() - } - - environment 'AIRBYTE_ROLE', System.getenv('AIRBYTE_ROLE') - environment 'AIRBYTE_VERSION', env.VERSION - environment 'DATABASE_URL', 'jdbc:postgresql://localhost:5432/airbyte' -} - -test { - // Required to enable mocked beans - systemProperty("mockito.test.enabled", "true") -} - -// produce reproducible archives -// (see https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives) -tasks.withType(AbstractArchiveTask) { - preserveFileTimestamps = false - reproducibleFileOrder = true -} - -tasks.named("buildDockerImage") { - dependsOn copyGeneratedTar -} - -Task publishArtifactsTask = getPublishArtifactsTask("$rootProject.ext.version", project) diff --git a/airbyte-bootloader/gradle.properties b/airbyte-bootloader/gradle.properties deleted file mode 100644 index 03cf6f2800519..0000000000000 --- a/airbyte-bootloader/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=bootloader diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/Application.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/Application.java deleted file mode 100644 index 35150ec706715..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/Application.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import io.micronaut.context.ApplicationContext; -import io.micronaut.runtime.Micronaut; -import lombok.extern.slf4j.Slf4j; - -/** - * Main application entry point responsible for starting the server and invoking the bootstrapping - * of the Airbyte environment. - */ -@Slf4j -public class Application { - - public static void main(final String[] args) { - try { - final ApplicationContext applicationContext = Micronaut.run(Application.class, args); - final Bootloader bootloader = applicationContext.getBean(Bootloader.class); - bootloader.load(); - System.exit(0); - } catch (final Exception e) { - log.error("Unable to bootstrap Airbyte environment.", e); - System.exit(-1); - } - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/Bootloader.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/Bootloader.java deleted file mode 100644 index 1785b31437aec..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/Bootloader.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Geography; -import io.airbyte.config.StandardWorkspace; -import io.airbyte.config.init.DefinitionsProvider; -import io.airbyte.config.init.PostLoadExecutor; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.db.init.DatabaseInitializationException; -import io.airbyte.db.init.DatabaseInitializer; -import io.airbyte.db.instance.DatabaseMigrator; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.validation.json.JsonValidationException; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.Optional; -import java.util.UUID; -import lombok.extern.slf4j.Slf4j; - -/** - * Ensures that the databases are migrated to the appropriate level. - */ -@Singleton -@Slf4j -public class Bootloader { - - private static final AirbyteVersion VERSION_BREAK = new AirbyteVersion("0.32.0-alpha"); - - private final boolean autoUpgradeConnectors; - private final ConfigRepository configRepository; - private final DatabaseMigrator configsDatabaseMigrator; - private final DatabaseInitializer configsDatabaseInitializer; - private final AirbyteVersion currentAirbyteVersion; - private final Optional definitionsProvider; - private final FeatureFlags featureFlags; - private final DatabaseInitializer jobsDatabaseInitializer; - private final DatabaseMigrator jobsDatabaseMigrator; - private final JobPersistence jobPersistence; - private final PostLoadExecutor postLoadExecution; - private final ProtocolVersionChecker protocolVersionChecker; - private final boolean runMigrationOnStartup; - private final SecretMigrator secretMigrator; - - public Bootloader( - @Value("${airbyte.bootloader.auto-upgrade-connectors}") final boolean autoUpgradeConnectors, - final ConfigRepository configRepository, - @Named("configsDatabaseInitializer") final DatabaseInitializer configsDatabaseInitializer, - @Named("configsDatabaseMigrator") final DatabaseMigrator configsDatabaseMigrator, - final AirbyteVersion currentAirbyteVersion, - final Optional definitionsProvider, - final FeatureFlags featureFlags, - @Named("jobsDatabaseInitializer") final DatabaseInitializer jobsDatabaseInitializer, - @Named("jobsDatabaseMigrator") final DatabaseMigrator jobsDatabaseMigrator, - final JobPersistence jobPersistence, - final ProtocolVersionChecker protocolVersionChecker, - @Value("${airbyte.bootloader.run-migration-on-startup}") final boolean runMigrationOnStartup, - final SecretMigrator secretMigrator, - final PostLoadExecutor postLoadExecution) { - this.autoUpgradeConnectors = autoUpgradeConnectors; - this.configRepository = configRepository; - this.configsDatabaseInitializer = configsDatabaseInitializer; - this.configsDatabaseMigrator = configsDatabaseMigrator; - this.currentAirbyteVersion = currentAirbyteVersion; - this.definitionsProvider = definitionsProvider; - this.featureFlags = featureFlags; - this.jobsDatabaseInitializer = jobsDatabaseInitializer; - this.jobsDatabaseMigrator = jobsDatabaseMigrator; - this.jobPersistence = jobPersistence; - this.protocolVersionChecker = protocolVersionChecker; - this.runMigrationOnStartup = runMigrationOnStartup; - this.secretMigrator = secretMigrator; - this.postLoadExecution = postLoadExecution; - } - - /** - * Performs all required bootstrapping for the Airbyte environment. This includes the following: - *
    - *
  • Initializes the databases
  • - *
  • Check database migration compatibility
  • - *
  • Check protocol version compatibility
  • - *
  • Migrate databases
  • - *
  • Create default workspace
  • - *
  • Create default deployment
  • - *
  • Perform post migration tasks
  • - *
- * - * @throws Exception if unable to perform any of the bootstrap operations. - */ - public void load() throws Exception { - log.info("Initializing databases..."); - initializeDatabases(); - - log.info("Checking migration compatibility..."); - assertNonBreakingMigration(jobPersistence, currentAirbyteVersion); - - log.info("Checking protocol version constraints..."); - assertNonBreakingProtocolVersionConstraints(protocolVersionChecker, jobPersistence, autoUpgradeConnectors); - - log.info("Running database migrations..."); - runFlywayMigration(runMigrationOnStartup, configsDatabaseMigrator, jobsDatabaseMigrator); - - log.info("Creating workspace (if none exists)..."); - createWorkspaceIfNoneExists(configRepository); - - log.info("Creating deployment (if none exists)..."); - createDeploymentIfNoneExists(jobPersistence); - - final String airbyteVersion = currentAirbyteVersion.serialize(); - log.info("Setting Airbyte version to '{}'...", airbyteVersion); - jobPersistence.setVersion(airbyteVersion); - log.info("Set version to '{}'", airbyteVersion); - - if (postLoadExecution != null) { - postLoadExecution.execute(); - log.info("Finished running post load Execution."); - } - - log.info("Finished bootstrapping Airbyte environment."); - } - - private void assertNonBreakingMigration(final JobPersistence jobPersistence, final AirbyteVersion airbyteVersion) - throws IOException { - // version in the database when the server main method is called. may be empty if this is the first - // time the server is started. - log.info("Checking for illegal upgrade..."); - final Optional initialAirbyteDatabaseVersion = jobPersistence.getVersion().map(AirbyteVersion::new); - if (!isLegalUpgrade(initialAirbyteDatabaseVersion.orElse(null), airbyteVersion)) { - final String attentionBanner = MoreResources.readResource("banner/attention-banner.txt"); - log.error(attentionBanner); - final String message = String.format( - "Cannot upgrade from version %s to version %s directly. First you must upgrade to version %s. After that upgrade is complete, you may upgrade to version %s", - initialAirbyteDatabaseVersion.get().serialize(), - airbyteVersion.serialize(), - VERSION_BREAK.serialize(), - airbyteVersion.serialize()); - - log.error(message); - throw new RuntimeException(message); - } - } - - private void assertNonBreakingProtocolVersionConstraints(final ProtocolVersionChecker protocolVersionChecker, - final JobPersistence jobPersistence, - final boolean autoUpgradeConnectors) - throws Exception { - final Optional newProtocolRange = protocolVersionChecker.validate(autoUpgradeConnectors); - if (newProtocolRange.isEmpty()) { - throw new RuntimeException( - "Aborting bootloader to avoid breaking existing connection after an upgrade. " + - "Please address airbyte protocol version support issues in the connectors before retrying."); - } - trackProtocolVersion(jobPersistence, newProtocolRange.get()); - } - - private void createDeploymentIfNoneExists(final JobPersistence jobPersistence) throws IOException { - final Optional deploymentOptional = jobPersistence.getDeployment(); - if (deploymentOptional.isPresent()) { - log.info("Running deployment: {}", deploymentOptional.get()); - } else { - final UUID deploymentId = UUID.randomUUID(); - jobPersistence.setDeployment(deploymentId); - log.info("Created deployment: {}", deploymentId); - } - } - - private void createWorkspaceIfNoneExists(final ConfigRepository configRepository) throws JsonValidationException, IOException { - if (!configRepository.listStandardWorkspaces(true).isEmpty()) { - log.info("Workspace already exists for the deployment."); - return; - } - - final UUID workspaceId = UUID.randomUUID(); - final StandardWorkspace workspace = new StandardWorkspace() - .withWorkspaceId(workspaceId) - .withCustomerId(UUID.randomUUID()) - .withName(workspaceId.toString()) - .withSlug(workspaceId.toString()) - .withInitialSetupComplete(false) - .withDisplaySetupWizard(true) - .withTombstone(false) - .withDefaultGeography(Geography.AUTO); - // NOTE: it's safe to use the NoSecrets version since we know that the user hasn't supplied any - // secrets yet. - configRepository.writeStandardWorkspaceNoSecrets(workspace); - } - - private void initializeDatabases() throws DatabaseInitializationException { - log.info("Initializing databases..."); - configsDatabaseInitializer.initialize(); - jobsDatabaseInitializer.initialize(); - log.info("Databases initialized."); - } - - @VisibleForTesting - boolean isLegalUpgrade(final AirbyteVersion airbyteDatabaseVersion, final AirbyteVersion airbyteVersion) { - // means there was no previous version so upgrade even needs to happen. always legal. - if (airbyteDatabaseVersion == null) { - log.info("No previous Airbyte Version set."); - return true; - } - - log.info("Current Airbyte version: {}", airbyteDatabaseVersion); - log.info("Future Airbyte version: {}", airbyteVersion); - final var futureVersionIsAfterVersionBreak = airbyteVersion.greaterThan(VERSION_BREAK) || airbyteVersion.isDev(); - final var isUpgradingThroughVersionBreak = airbyteDatabaseVersion.lessThan(VERSION_BREAK) && futureVersionIsAfterVersionBreak; - return !isUpgradingThroughVersionBreak; - } - - private void runFlywayMigration(final boolean runDatabaseMigrationOnStartup, - final DatabaseMigrator configDbMigrator, - final DatabaseMigrator jobDbMigrator) { - log.info("Creating baseline for config database..."); - configDbMigrator.createBaseline(); - log.info("Creating baseline for job database..."); - jobDbMigrator.createBaseline(); - - if (runDatabaseMigrationOnStartup) { - log.info("Migrating configs database..."); - configDbMigrator.migrate(); - log.info("Migrating jobs database..."); - jobDbMigrator.migrate(); - } else { - log.info("Auto database migration has been skipped."); - } - } - - private void trackProtocolVersion(final JobPersistence jobPersistence, final AirbyteProtocolVersionRange protocolVersionRange) - throws IOException { - jobPersistence.setAirbyteProtocolVersionMin(protocolVersionRange.min()); - jobPersistence.setAirbyteProtocolVersionMax(protocolVersionRange.max()); - log.info("AirbyteProtocol version support range: [{}:{}]", protocolVersionRange.min().serialize(), protocolVersionRange.max().serialize()); - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/DefaultPostLoadExecutor.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/DefaultPostLoadExecutor.java deleted file mode 100644 index ce92c1f42afa2..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/DefaultPostLoadExecutor.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.config.init.ApplyDefinitionsHelper; -import io.airbyte.config.init.PostLoadExecutor; -import io.airbyte.persistence.job.JobPersistence; -import jakarta.inject.Singleton; -import lombok.extern.slf4j.Slf4j; - -/** - * Default implementation of the tasks that should be executed after a successful bootstrapping of - * the Airbyte environment. - *

- *

- * This implementation performs the following tasks: - *

    - *
  • Applies the latest definitions from the provider to the repository
  • - *
  • If enables, migrates secrets
  • - *
- */ -@Singleton -@Slf4j -public class DefaultPostLoadExecutor implements PostLoadExecutor { - - private final ApplyDefinitionsHelper applyDefinitionsHelper; - private final FeatureFlags featureFlags; - private final JobPersistence jobPersistence; - private final SecretMigrator secretMigrator; - - public DefaultPostLoadExecutor(final ApplyDefinitionsHelper applyDefinitionsHelper, - final FeatureFlags featureFlags, - final JobPersistence jobPersistence, - final SecretMigrator secretMigrator) { - this.applyDefinitionsHelper = applyDefinitionsHelper; - this.featureFlags = featureFlags; - this.jobPersistence = jobPersistence; - this.secretMigrator = secretMigrator; - } - - @Override - public void execute() throws Exception { - applyDefinitionsHelper.apply(); - - if (featureFlags.forceSecretMigration() || !jobPersistence.isSecretMigrated()) { - if (this.secretMigrator != null) { - this.secretMigrator.migrateSecrets(); - log.info("Secrets successfully migrated."); - } - } - log.info("Loaded seed data."); - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/ProtocolVersionChecker.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/ProtocolVersionChecker.java deleted file mode 100644 index c03cfde922c86..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/ProtocolVersionChecker.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import io.airbyte.commons.version.AirbyteProtocolVersion; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorType; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.init.DefinitionsProvider; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.JobPersistence; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import lombok.extern.slf4j.Slf4j; - -/** - * Validates that all connectors support the desired target Airbyte protocol version. - */ -@Singleton -@Slf4j -public class ProtocolVersionChecker { - - private final JobPersistence jobPersistence; - private final AirbyteProtocolVersionRange airbyteProtocolTargetVersionRange; - private final ConfigRepository configRepository; - private final Optional definitionsProvider; - - /** - * Constructs a new protocol version checker that verifies all connectors are within the provided - * target protocol version range. - * - * @param jobPersistence A {@link JobPersistence} instance. - * @param airbyteProtocolTargetVersionRange The target Airbyte protocol version range. - * @param configRepository A {@link ConfigRepository} instance - * @param definitionsProvider An {@link Optional} that may contain a {@link DefinitionsProvider} - * instance. - */ - public ProtocolVersionChecker(final JobPersistence jobPersistence, - final AirbyteProtocolVersionRange airbyteProtocolTargetVersionRange, - final ConfigRepository configRepository, - final Optional definitionsProvider) { - this.jobPersistence = jobPersistence; - this.airbyteProtocolTargetVersionRange = airbyteProtocolTargetVersionRange; - this.configRepository = configRepository; - this.definitionsProvider = definitionsProvider; - } - - /** - * Validate the AirbyteProtocolVersion support range between the platform and the connectors. - *

- * The goal is to make sure that we do not end up disabling existing connections after an upgrade - * that changes the protocol support range. - * - * @param supportAutoUpgrade whether the connectors will be automatically upgraded by the platform - * @return the supported protocol version range if check is successful, Optional.empty() if we would - * break existing connections. - * @throws IOException - */ - public Optional validate(final boolean supportAutoUpgrade) throws IOException { - final Optional currentAirbyteVersion = getCurrentAirbyteVersion(); - final Optional currentRange = jobPersistence.getCurrentProtocolVersionRange(); - final AirbyteProtocolVersionRange targetRange = getTargetProtocolVersionRange(); - - // Checking if there is a pre-existing version of airbyte. - // Without this check, the first run of the validation would fail because we do not have the tables - // set yet - // which means that the actor definitions lookup will throw SQLExceptions. - if (currentAirbyteVersion.isEmpty()) { - log.info("No previous version of Airbyte detected, assuming this is a fresh deploy."); - return Optional.of(targetRange); - } - - if (currentRange.isEmpty() || currentRange.get().equals(targetRange)) { - log.info("Using AirbyteProtocolVersion range [{}:{}]", targetRange.min().serialize(), targetRange.max().serialize()); - return Optional.of(targetRange); - } - - log.info("Detected an AirbyteProtocolVersion range change from [{}:{}] to [{}:{}]", - currentRange.get().min().serialize(), currentRange.get().max().serialize(), - targetRange.min().serialize(), targetRange.max().serialize()); - - final Map> conflicts = getConflictingActorDefinitions(targetRange); - - if (conflicts.isEmpty()) { - log.info("No protocol version conflict detected."); - return Optional.of(targetRange); - } - - final Set destConflicts = conflicts.getOrDefault(ActorType.DESTINATION, new HashSet<>()); - final Set sourceConflicts = conflicts.getOrDefault(ActorType.SOURCE, new HashSet<>()); - - if (!supportAutoUpgrade) { - // If we do not support auto upgrade, any conflict of used connectors must be resolved before being - // able to upgrade the platform. - log.warn("The following connectors need to be upgraded before being able to upgrade the platform"); - formatActorDefinitionForLogging(destConflicts, sourceConflicts).forEach(log::warn); - return Optional.empty(); - } - - final Set remainingDestConflicts = - projectRemainingConflictsAfterConnectorUpgrades(targetRange, destConflicts, ActorType.DESTINATION); - final Set remainingSourceConflicts = - projectRemainingConflictsAfterConnectorUpgrades(targetRange, sourceConflicts, ActorType.SOURCE); - - if (!remainingDestConflicts.isEmpty() || !remainingSourceConflicts.isEmpty()) { - // These set of connectors need a manual intervention because there is no compatible version listed - formatActorDefinitionForLogging(remainingDestConflicts, remainingSourceConflicts).forEach(log::warn); - return Optional.empty(); - } - - // These can be auto upgraded - destConflicts.removeAll(remainingDestConflicts); - sourceConflicts.removeAll(remainingSourceConflicts); - log.info("The following connectors will be upgraded"); - formatActorDefinitionForLogging(destConflicts, sourceConflicts).forEach(log::info); - return Optional.of(targetRange); - } - - protected Optional getCurrentAirbyteVersion() throws IOException { - return jobPersistence.getVersion().map(AirbyteVersion::new); - } - - protected AirbyteProtocolVersionRange getTargetProtocolVersionRange() { - return airbyteProtocolTargetVersionRange; - } - - protected Map> getConflictingActorDefinitions(final AirbyteProtocolVersionRange targetRange) throws IOException { - final Map> actorDefIdToProtocolVersion = configRepository.getActorDefinitionToProtocolVersionMap(); - final Map> conflicts = - actorDefIdToProtocolVersion.entrySet().stream() - // Keeping only ActorDefinitionIds that have an unsupported protocol version - .filter(e -> !targetRange.isSupported(e.getValue().getValue())) - // Build the ActorType -> List[ActorDefIds] map - .map(e -> Map.entry(e.getValue().getKey(), e.getKey())) - // Group by ActorType and transform the List> into a Set - .collect(Collectors.groupingBy(Entry::getKey, - Collectors.collectingAndThen(Collectors.toList(), list -> list.stream().map(Entry::getValue).collect(Collectors.toSet())))); - return conflicts; - } - - protected Set projectRemainingConflictsAfterConnectorUpgrades(final AirbyteProtocolVersionRange targetRange, - final Set initialConflicts, - final ActorType actorType) { - if (initialConflicts.isEmpty()) { - return Set.of(); - } - - final Set upgradedSourceDefs = getProtocolVersionsForActorDefinitions(actorType) - // Keep definition ids if the protocol version will fall into the new supported range - .filter(e -> initialConflicts.contains(e.getKey()) && targetRange.isSupported(e.getValue())) - .map(Entry::getKey) - .collect(Collectors.toSet()); - - // Get the set of source definitions that will still have conflict after the connector upgrades - final Set remainingConflicts = new HashSet<>(initialConflicts); - remainingConflicts.removeAll(upgradedSourceDefs); - return remainingConflicts; - } - - protected Stream> getProtocolVersionsForActorDefinitions(final ActorType actorType) { - if (definitionsProvider.isEmpty()) { - return Stream.empty(); - } - - return getActorVersions(actorType); - } - - private Stream> getActorVersions(final ActorType actorType) { - switch (actorType) { - case SOURCE: - return definitionsProvider.get().getSourceDefinitions() - .stream() - .map(def -> Map.entry(def.getSourceDefinitionId(), AirbyteProtocolVersion.getWithDefault(def.getSpec().getProtocolVersion()))); - case DESTINATION: - default: - return definitionsProvider.get().getDestinationDefinitions() - .stream() - .map(def -> Map.entry(def.getDestinationDefinitionId(), AirbyteProtocolVersion.getWithDefault(def.getSpec().getProtocolVersion()))); - } - } - - private Stream formatActorDefinitionForLogging(final Set remainingDestConflicts, final Set remainingSourceConflicts) { - return Stream.concat( - remainingSourceConflicts.stream().map(defId -> { - final StandardSourceDefinition sourceDef; - try { - sourceDef = configRepository.getStandardSourceDefinition(defId); - return String.format("Source: %s: %s: protocol version: %s", - sourceDef.getSourceDefinitionId(), sourceDef.getName(), sourceDef.getProtocolVersion()); - } catch (final Exception e) { - log.info("Failed to getStandardSourceDefinition for {}", defId, e); - return String.format("Source: %s: Failed to fetch details...", defId); - } - }), - remainingDestConflicts.stream().map(defId -> { - try { - final StandardDestinationDefinition destDef = configRepository.getStandardDestinationDefinition(defId); - return String.format("Destination: %s: %s: protocol version: %s", - destDef.getDestinationDefinitionId(), destDef.getName(), destDef.getProtocolVersion()); - } catch (final Exception e) { - log.info("Failed to getStandardDestinationDefinition for {}", defId, e); - return String.format("Source: %s: Failed to fetch details...", defId); - } - })); - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/SecretMigrator.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/SecretMigrator.java deleted file mode 100644 index 451995f4af40e..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/SecretMigrator.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import lombok.Value; -import lombok.extern.slf4j.Slf4j; - -@Singleton -@Slf4j -public class SecretMigrator { - - private final SecretsRepositoryReader secretsReader; - private final SecretsRepositoryWriter secretsWriter; - private final ConfigRepository configRepository; - private final JobPersistence jobPersistence; - private final Optional secretPersistence; - - public SecretMigrator(final SecretsRepositoryReader secretsReader, - final SecretsRepositoryWriter secretsWriter, - final ConfigRepository configRepository, - final JobPersistence jobPersistence, - @Named("secretPersistence") final Optional secretPersistence) { - this.secretsReader = secretsReader; - this.secretsWriter = secretsWriter; - this.configRepository = configRepository; - this.jobPersistence = jobPersistence; - this.secretPersistence = secretPersistence; - } - - @Value - static class ConnectorConfiguration { - - private final UUID workspace; - private final JsonNode configuration; - private final JsonNode spec; - - } - - /** - * Perform a secret migration. It will load all the actor specs extract the secret JsonPath from it. - * Then for all the secret that are stored in a plain text format, it will save the plain text in - * the secret manager and store the coordinate in the config DB. - */ - public void migrateSecrets() throws Exception { - if (secretPersistence.isEmpty()) { - log.info("No secret persistence is provided, the migration won't be run "); - - return; - } else { - secretPersistence.get().initialize(); - } - - final List standardSourceDefinitions = configRepository.listStandardSourceDefinitions(true); - - final Map definitionIdToSourceSpecs = standardSourceDefinitions - .stream().collect(Collectors.toMap(StandardSourceDefinition::getSourceDefinitionId, StandardSourceDefinition::getSpec)); - - final List sourcesWithoutSecrets = configRepository.listSourceConnection(); - final List sourcesWithSecrets = new ArrayList<>(); - for (final SourceConnection source : sourcesWithoutSecrets) { - final SourceConnection sourceWithSecrets = secretsReader.getSourceConnectionWithSecrets(source.getSourceId()); - sourcesWithSecrets.add(sourceWithSecrets); - } - - migrateSources(sourcesWithSecrets, definitionIdToSourceSpecs); - - final List standardDestinationDefinitions = configRepository.listStandardDestinationDefinitions(true); - - final Map definitionIdToDestinationSpecs = standardDestinationDefinitions.stream() - .collect(Collectors.toMap(StandardDestinationDefinition::getDestinationDefinitionId, StandardDestinationDefinition::getSpec)); - - final List destinationsWithoutSecrets = configRepository.listDestinationConnection(); - final List destinationsWithSecrets = new ArrayList<>(); - for (final DestinationConnection destination : destinationsWithoutSecrets) { - final DestinationConnection destinationWithoutSecrets = secretsReader.getDestinationConnectionWithSecrets(destination.getDestinationId()); - destinationsWithSecrets.add(destinationWithoutSecrets); - } - - migrateDestinations(destinationsWithSecrets, definitionIdToDestinationSpecs); - - jobPersistence.setSecretMigrationDone(); - } - - /** - * This is migrating the secrets for the source actors - */ - @VisibleForTesting - void migrateSources(final List sources, final Map definitionIdToSourceSpecs) - throws JsonValidationException, IOException { - log.info("Migrating Sources"); - for (final SourceConnection source : sources) { - final Optional specOptional = Optional.ofNullable(definitionIdToSourceSpecs.get(source.getSourceDefinitionId())); - - if (specOptional.isPresent()) { - secretsWriter.writeSourceConnection(source, specOptional.get()); - } else { - // if the spec can't be found, don't risk writing secrets to db. wipe out the configuration for the - // connector. - final SourceConnection sourceWithConfigRemoved = Jsons.clone(source); - sourceWithConfigRemoved.setConfiguration(Jsons.emptyObject()); - secretsWriter.writeSourceConnection(sourceWithConfigRemoved, new ConnectorSpecification().withConnectionSpecification(Jsons.emptyObject())); - } - } - } - - /** - * This is migrating the secrets for the destination actors - */ - @VisibleForTesting - void migrateDestinations(final List destinations, final Map definitionIdToDestinationSpecs) - throws JsonValidationException, IOException { - log.info("Migration Destinations"); - for (final DestinationConnection destination : destinations) { - final Optional specOptional = - Optional.ofNullable(definitionIdToDestinationSpecs.get(destination.getDestinationDefinitionId())); - - if (specOptional.isPresent()) { - secretsWriter.writeDestinationConnection(destination, specOptional.get()); - } else { - // if the spec can't be found, don't risk writing secrets to db. wipe out the configuration for the - // connector. - final DestinationConnection destinationWithConfigRemoved = Jsons.clone(destination); - destinationWithConfigRemoved.setConfiguration(Jsons.emptyObject()); - secretsWriter.writeDestinationConnection(destinationWithConfigRemoved, - new ConnectorSpecification().withConnectionSpecification(Jsons.emptyObject())); - } - } - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/ApplicationBeanFactory.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/ApplicationBeanFactory.java deleted file mode 100644 index df2ced11ef733..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/ApplicationBeanFactory.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader.config; - -import io.airbyte.commons.features.EnvVariableFeatureFlags; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.commons.version.Version; -import io.airbyte.config.init.DefinitionsProvider; -import io.airbyte.config.init.LocalDefinitionsProvider; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.config.persistence.split_secrets.SecretsHydrator; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.Optional; - -/** - * Micronaut bean factory for general application-related singletons. - */ -@Factory -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class ApplicationBeanFactory { - - @Singleton - public AirbyteVersion airbyteVersion(@Value("${airbyte.version}") final String version) { - return new AirbyteVersion(version); - } - - @Singleton - public AirbyteProtocolVersionRange airbyteProtocolTargetVersionRange(@Value("${airbyte.protocol.target.range.min-version}") final String min, - @Value("${airbyte.protocol.target.range.max-version}") final String max) { - return new AirbyteProtocolVersionRange(new Version(min), new Version(max)); - } - - @Singleton - public DefinitionsProvider localDefinitionsProvider() throws IOException { - return new LocalDefinitionsProvider(); - } - - @Singleton - public FeatureFlags featureFlags() { - return new EnvVariableFeatureFlags(); - } - - @Singleton - public JsonSecretsProcessor jsonSecretsProcessor() { - return JsonSecretsProcessor.builder() - .copySecrets(false) - .build(); - } - - @Singleton - public SecretsRepositoryReader secretsRepositoryReader(final ConfigRepository configRepository, final SecretsHydrator secretsHydrator) { - return new SecretsRepositoryReader(configRepository, secretsHydrator); - } - - @Singleton - public SecretsRepositoryWriter secretsRepositoryWriter(final ConfigRepository configRepository, - @Named("secretPersistence") final Optional secretPersistence, - @Named("ephemeralSecretPersistence") final Optional ephemeralSecretPersistence) { - return new SecretsRepositoryWriter(configRepository, secretPersistence, ephemeralSecretPersistence); - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/DatabaseBeanFactory.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/DatabaseBeanFactory.java deleted file mode 100644 index f3a77957b919e..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/DatabaseBeanFactory.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader.config; - -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.db.Database; -import io.airbyte.db.check.impl.JobsDatabaseAvailabilityCheck; -import io.airbyte.db.factory.DatabaseCheckFactory; -import io.airbyte.db.init.DatabaseInitializer; -import io.airbyte.db.instance.DatabaseConstants; -import io.airbyte.db.instance.DatabaseMigrator; -import io.airbyte.db.instance.configs.ConfigsDatabaseMigrator; -import io.airbyte.db.instance.jobs.JobsDatabaseMigrator; -import io.airbyte.persistence.job.DefaultJobPersistence; -import io.airbyte.persistence.job.JobPersistence; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import io.micronaut.flyway.FlywayConfigurationProperties; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import javax.sql.DataSource; -import org.flywaydb.core.Flyway; -import org.jooq.DSLContext; - -/** - * Micronaut bean factory for database-related singletons. - */ -@Factory -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class DatabaseBeanFactory { - - private static final String BASELINE_DESCRIPTION = "Baseline from file-based migration v1"; - private static final Boolean BASELINE_ON_MIGRATION = true; - private static final String INSTALLED_BY = "BootloaderApp"; - - @Singleton - @Named("configDatabase") - public Database configDatabase(@Named("config") final DSLContext dslContext) throws IOException { - return new Database(dslContext); - } - - @Singleton - @Named("jobsDatabase") - public Database jobsDatabase(@Named("jobs") final DSLContext dslContext) throws IOException { - return new Database(dslContext); - } - - @Singleton - @Named("configFlyway") - public Flyway configFlyway(@Named("config") final FlywayConfigurationProperties configFlywayConfigurationProperties, - @Named("config") final DataSource configDataSource, - @Value("${airbyte.bootloader.migration-baseline-version}") final String baselineVersion) { - return configFlywayConfigurationProperties.getFluentConfiguration() - .dataSource(configDataSource) - .baselineVersion(baselineVersion) - .baselineDescription(BASELINE_DESCRIPTION) - .baselineOnMigrate(BASELINE_ON_MIGRATION) - .installedBy(INSTALLED_BY) - .table(String.format("airbyte_%s_migrations", "configs")) - .load(); - } - - @Singleton - @Named("jobsFlyway") - public Flyway jobsFlyway(@Named("jobs") final FlywayConfigurationProperties jobsFlywayConfigurationProperties, - @Named("jobs") final DataSource jobsDataSource, - @Value("${airbyte.bootloader.migration-baseline-version}") final String baselineVersion) { - return jobsFlywayConfigurationProperties.getFluentConfiguration() - .dataSource(jobsDataSource) - .baselineVersion(baselineVersion) - .baselineDescription(BASELINE_DESCRIPTION) - .baselineOnMigrate(BASELINE_ON_MIGRATION) - .installedBy(INSTALLED_BY) - .table(String.format("airbyte_%s_migrations", "jobs")) - .load(); - } - - @Singleton - public ConfigRepository configRepository(@Named("configDatabase") final Database configDatabase) { - return new ConfigRepository(configDatabase); - } - - @Singleton - public JobPersistence jobPersistence(@Named("jobsDatabase") final Database jobDatabase) { - return new DefaultJobPersistence(jobDatabase); - } - - @Singleton - @Named("configsDatabaseInitializer") - public DatabaseInitializer configsDatabaseInitializer(@Named("config") final DSLContext configsDslContext, - @Value("${airbyte.flyway.configs.initialization-timeout-ms}") final Long configsDatabaseInitializationTimeoutMs) - throws IOException { - return DatabaseCheckFactory.createConfigsDatabaseInitializer(configsDslContext, - configsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.CONFIGS_INITIAL_SCHEMA_PATH)); - } - - @Singleton - @Named("jobsDatabaseInitializer") - public DatabaseInitializer jobsDatabaseInitializer(@Named("jobs") final DSLContext jobsDslContext, - @Value("${airbyte.flyway.jobs.initialization-timeout-ms}") final Long jobsDatabaseInitializationTimeoutMs) - throws IOException { - return DatabaseCheckFactory.createJobsDatabaseInitializer(jobsDslContext, - jobsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.JOBS_INITIAL_SCHEMA_PATH)); - } - - @Singleton - @Named("jobsDatabaseAvailabilityCheck") - public JobsDatabaseAvailabilityCheck jobsDatabaseAvailabilityCheck(@Named("jobs") final DSLContext dslContext) { - return new JobsDatabaseAvailabilityCheck(dslContext, DatabaseConstants.DEFAULT_ASSERT_DATABASE_TIMEOUT_MS); - } - - @Singleton - @Named("configsDatabaseMigrator") - public DatabaseMigrator configsDatabaseMigrator(@Named("configDatabase") final Database configDatabase, - @Named("configFlyway") final Flyway configFlyway) { - return new ConfigsDatabaseMigrator(configDatabase, configFlyway); - } - - @Singleton - @Named("jobsDatabaseMigrator") - public DatabaseMigrator jobsDatabaseMigrator(@Named("jobsDatabase") final Database jobsDatabase, - @Named("jobsFlyway") final Flyway jobsFlyway) { - return new JobsDatabaseMigrator(jobsDatabase, jobsFlyway); - } - -} diff --git a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/SecretPersistenceBeanFactory.java b/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/SecretPersistenceBeanFactory.java deleted file mode 100644 index 15e9720d23b6c..0000000000000 --- a/airbyte-bootloader/src/main/java/io/airbyte/bootloader/config/SecretPersistenceBeanFactory.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader.config; - -import io.airbyte.config.persistence.split_secrets.AWSSecretManagerPersistence; -import io.airbyte.config.persistence.split_secrets.GoogleSecretManagerPersistence; -import io.airbyte.config.persistence.split_secrets.LocalTestingSecretPersistence; -import io.airbyte.config.persistence.split_secrets.RealSecretsHydrator; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.config.persistence.split_secrets.SecretsHydrator; -import io.airbyte.config.persistence.split_secrets.VaultSecretPersistence; -import io.airbyte.db.Database; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Named; -import jakarta.inject.Singleton; - -/** - * Micronaut bean factory for secret persistence-related singletons. - */ -@Factory -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class SecretPersistenceBeanFactory { - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!testing_config_db_table).*") - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!google_secret_manager).*") - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!vault).*") - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!aws_secret_manager).*") - @Named("secretPersistence") - public SecretPersistence defaultSecretPersistence(@Named("configDatabase") final Database configDatabase) { - return localTestingSecretPersistence(configDatabase); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^testing_config_db_table$") - @Named("secretPersistence") - public SecretPersistence localTestingSecretPersistence(@Named("configDatabase") final Database configDatabase) { - return new LocalTestingSecretPersistence(configDatabase); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^testing_config_db_table$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralLocalTestingSecretPersistence(@Named("configDatabase") final Database configDatabase) { - return new LocalTestingSecretPersistence(configDatabase); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^google_secret_manager$") - @Named("secretPersistence") - public SecretPersistence googleSecretPersistence(@Value("${airbyte.secret.store.gcp.credentials}") final String credentials, - @Value("${airbyte.secret.store.gcp.project-id}") final String projectId) { - return GoogleSecretManagerPersistence.getLongLived(projectId, credentials); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^google_secret_manager$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralGoogleSecretPersistence(@Value("${airbyte.secret.store.gcp.credentials}") final String credentials, - @Value("${airbyte.secret.store.gcp.project-id}") final String projectId) { - return GoogleSecretManagerPersistence.getEphemeral(projectId, credentials); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^vault$") - @Named("secretPersistence") - public SecretPersistence vaultSecretPersistence(@Value("${airbyte.secret.store.vault.address}") final String address, - @Value("${airbyte.secret.store.vault.prefix}") final String prefix, - @Value("${airbyte.secret.store.vault.token}") final String token) { - return new VaultSecretPersistence(address, prefix, token); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^vault$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralVaultSecretPersistence(@Value("${airbyte.secret.store.vault.address}") final String address, - @Value("${airbyte.secret.store.vault.prefix}") final String prefix, - @Value("${airbyte.secret.store.vault.token}") final String token) { - return new VaultSecretPersistence(address, prefix, token); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^aws_secret_manager$") - @Named("secretPersistence") - public SecretPersistence awsSecretPersistence(@Value("${airbyte.secret.store.aws.access-key}") final String awsAccessKey, - @Value("${airbyte.secret.store.aws.secret-key}") final String awsSecretKey) { - return new AWSSecretManagerPersistence(awsAccessKey, awsSecretKey); - } - - @Singleton - public SecretsHydrator secretsHydrator(@Named("secretPersistence") final SecretPersistence secretPersistence) { - return new RealSecretsHydrator(secretPersistence); - } - -} diff --git a/airbyte-bootloader/src/main/resources/application.yml b/airbyte-bootloader/src/main/resources/application.yml deleted file mode 100644 index 38ed361e5e0cb..0000000000000 --- a/airbyte-bootloader/src/main/resources/application.yml +++ /dev/null @@ -1,121 +0,0 @@ -micronaut: - application: - name: airbyte-bootloader - server: - port: 9002 - -airbyte: - bootloader: - auto-upgrade-connectors: ${AUTO_UPGRADE_CONNECTORS_PROTOCOL:false} - migration-baseline-version: ${BOOTLOADER_MIGRATION_BASELINE_VERSION:0.29.0.001} - run-migration-on-startup: ${RUN_DATABASE_MIGRATION_ON_STARTUP:true} - flyway: - configs: - initialization-timeout-ms: ${CONFIGS_DATABASE_INITIALIZATION_TIMEOUT_MS:60000} - jobs: - initialization-timeout-ms: ${JOBS_DATABASE_INITIALIZATION_TIMEOUT_MS:60000} - platform: - remote-connector-catalog: - timeout-ms: ${REMOTE_CONNECTOR_CATALOG_MS:10000} - url: ${REMOTE_CONNECTOR_CATALOG_URL:} - protocol: - target: - range: - min-version: ${AIRBYTE_PROTOCOL_VERSION_MIN:0.0.0} - max-version: ${AIRBYTE_PROTOCOL_VERSION_MAX:0.3.0} - secret: - persistence: ${SECRET_PERSISTENCE:TESTING_CONFIG_DB_TABLE} - store: - aws: - access-key: ${AWS_ACCESS_KEY:} - secret-key: ${AWS_SECRET_ACCESS_KEY:} - gcp: - credentials: ${SECRET_STORE_GCP_CREDENTIALS:} - project-id: ${SECRET_STORE_GCP_PROJECT_ID:} - vault: - address: ${VAULT_ADDRESS:} - prefix: ${VAULT_PREFIX:} - token: ${VAULT_AUTH_TOKEN:} - version: ${AIRBYTE_VERSION} - -datasources: - config: - connection-test-query: SELECT 1 - connection-timeout: 30000 - idle-timeout: 600000 - initialization-fail-timeout: -1 # Disable fail fast checking to avoid issues due to other pods not being started in time - maximum-pool-size: 5 - minimum-idle: 0 - url: ${DATABASE_URL} - driverClassName: org.postgresql.Driver - username: ${DATABASE_USER} - password: ${DATABASE_PASSWORD} - jobs: - connection-test-query: SELECT 1 - connection-timeout: 30000 - idle-timeout: 600000 - initialization-fail-timeout: -1 # Disable fail fast checking to avoid issues due to other pods not being started in time - maximum-pool-size: 5 - minimum-idle: 0 - url: ${DATABASE_URL} - driverClassName: org.postgresql.Driver - username: ${DATABASE_USER} - password: ${DATABASE_PASSWORD} - -endpoints: - beans: - enabled: true - sensitive: false - env: - enabled: true - sensitive: false - health: - enabled: true - sensitive: false - info: - enabled: true - sensitive: true - loggers: - enabled: true - sensitive: true - refresh: - enabled: false - sensitive: true - routes: - enabled: true - sensitive: false - threaddump: - enabled: true - sensitive: true - -flyway: - enabled: true - datasources: - config: - enabled: false - locations: - - 'classpath:io/airbyte/db/instance/configs/migrations' - jobs: - enabled: false - locations: - - 'classpath:io/airbyte/db/instance/jobs/migrations' - -jpa: - default: - properties: - hibernate: - show_sql: true - -jooq: - datasources: - config: - jackson-converter-enabled: true - sql-dialect: POSTGRES - jobs: - jackson-converter-enabled: true - sql-dialect: POSTGRES - -logger: - levels: -# Uncomment to help resolve issues with conditional beans -# io.micronaut.context.condition: DEBUG \ No newline at end of file diff --git a/airbyte-bootloader/src/main/resources/banner/attention-banner.txt b/airbyte-bootloader/src/main/resources/banner/attention-banner.txt deleted file mode 100644 index e35652b219ef9..0000000000000 --- a/airbyte-bootloader/src/main/resources/banner/attention-banner.txt +++ /dev/null @@ -1,13 +0,0 @@ - ___ ___________________ ________________ _ __ - / |/_ __/_ __/ ____/ | / /_ __/ _/ __ \/ | / / - ________________________ / /| | / / / / / __/ / |/ / / / / // / / / |/ / ________________________ -/_____/_____/_____/_____/ / ___ |/ / / / / /___/ /| / / / _/ // /_/ / /| / /_____/_____/_____/_____/ - __ _______ __________ /_/ _|_/_/ _/_/_/_____/_/_|_/_/_/ /___/\____/_/_|_/ __ __________ __________ - / / / / ___// ____/ __ \ / _/ | / / __ \/ / / /_ __/ / __ \/ ____/ __ \/ / / / _/ __ \/ ____/ __ \ - / / / /\__ \/ __/ / /_/ / / // |/ / /_/ / / / / / / / /_/ / __/ / / / / / / // // /_/ / __/ / / / / -/ /_/ /___/ / /___/ _, _/ _/ // /| / ____/ /_/ / / / / _, _/ /___/ /_/ / /_/ // // _, _/ /___/ /_/ / -\____//____/_____/_/ |_| /___/_/ |_/_/ \____/ /_/ /_/ |_/_____/\___\_\____/___/_/ |_/_____/_____/ - - ------------------- - See details below - ------------------- diff --git a/airbyte-bootloader/src/main/resources/micronaut-banner.txt b/airbyte-bootloader/src/main/resources/micronaut-banner.txt deleted file mode 100644 index ec2646448f420..0000000000000 --- a/airbyte-bootloader/src/main/resources/micronaut-banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - - ___ _ __ __ - / | (_)____/ /_ __ __/ /____ - / /| | / / ___/ __ \/ / / / __/ _ \ - / ___ |/ / / / /_/ / /_/ / /_/ __/ -/_/ |_/_/_/ /_.___/\__, /\__/\___/ - /____/ - : airbyte-bootloader : \ No newline at end of file diff --git a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderTest.java b/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderTest.java deleted file mode 100644 index 14e0bb7c6aeed..0000000000000 --- a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/BootloaderTest.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import static io.airbyte.config.Configs.SecretPersistenceType.TESTING_CONFIG_DB_TABLE; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.ObjectMapper; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.commons.version.Version; -import io.airbyte.config.Configs; -import io.airbyte.config.Geography; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardWorkspace; -import io.airbyte.config.init.ApplyDefinitionsHelper; -import io.airbyte.config.init.DefinitionsProvider; -import io.airbyte.config.init.LocalDefinitionsProvider; -import io.airbyte.config.init.PostLoadExecutor; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.LocalTestingSecretPersistence; -import io.airbyte.config.persistence.split_secrets.RealSecretsHydrator; -import io.airbyte.db.factory.DSLContextFactory; -import io.airbyte.db.factory.DataSourceFactory; -import io.airbyte.db.factory.DatabaseCheckFactory; -import io.airbyte.db.factory.FlywayFactory; -import io.airbyte.db.instance.DatabaseConstants; -import io.airbyte.db.instance.configs.ConfigsDatabaseMigrator; -import io.airbyte.db.instance.configs.ConfigsDatabaseTestProvider; -import io.airbyte.db.instance.jobs.JobsDatabaseMigrator; -import io.airbyte.db.instance.jobs.JobsDatabaseTestProvider; -import io.airbyte.persistence.job.DefaultJobPersistence; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.sql.DataSource; -import lombok.val; -import org.flywaydb.core.Flyway; -import org.jooq.SQLDialect; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.testcontainers.containers.PostgreSQLContainer; -import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; -import uk.org.webcompere.systemstubs.jupiter.SystemStub; -import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; - -/** - * Test suite for the {@link Bootloader} class. - */ -@SuppressWarnings("PMD.AvoidUsingHardCodedIP") -@ExtendWith(SystemStubsExtension.class) -class BootloaderTest { - - private PostgreSQLContainer container; - private DataSource configsDataSource; - private DataSource jobsDataSource; - private static final String DOCKER = "docker"; - private static final String PROTOCOL_VERSION_123 = "1.2.3"; - private static final String PROTOCOL_VERSION_124 = "1.2.4"; - private static final String VERSION_0330_ALPHA = "0.33.0-alpha"; - private static final String VERSION_0320_ALPHA = "0.32.0-alpha"; - private static final String VERSION_0321_ALPHA = "0.32.1-alpha"; - private static final String VERSION_0170_ALPHA = "0.17.0-alpha"; - - // ⚠️ This line should change with every new migration to show that you meant to make a new - // migration to the prod database - private static final String CURRENT_CONFIGS_MIGRATION_VERSION = "0.40.28.001"; - private static final String CURRENT_JOBS_MIGRATION_VERSION = "0.40.28.001"; - - @BeforeEach - void setup() { - container = new PostgreSQLContainer<>("postgres:13-alpine") - .withDatabaseName("public") - .withUsername(DOCKER) - .withPassword(DOCKER); - container.start(); - - configsDataSource = - DataSourceFactory.create(container.getUsername(), container.getPassword(), container.getDriverClassName(), container.getJdbcUrl()); - jobsDataSource = - DataSourceFactory.create(container.getUsername(), container.getPassword(), container.getDriverClassName(), container.getJdbcUrl()); - } - - @AfterEach - void cleanup() throws Exception { - closeDataSource(configsDataSource); - closeDataSource(jobsDataSource); - container.stop(); - } - - @SystemStub - private EnvironmentVariables environmentVariables; - - @Test - void testBootloaderAppBlankDb() throws Exception { - val currentAirbyteVersion = new AirbyteVersion(VERSION_0330_ALPHA); - val airbyteProtocolRange = new AirbyteProtocolVersionRange(new Version(PROTOCOL_VERSION_123), new Version(PROTOCOL_VERSION_124)); - val mockedFeatureFlags = mock(FeatureFlags.class); - val runMigrationOnStartup = true; - val mockedSecretMigrator = mock(SecretMigrator.class); - - try (val configsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES); - val jobsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES)) { - - val configsFlyway = createConfigsFlyway(configsDataSource); - val jobsFlyway = createJobsFlyway(jobsDataSource); - - val configDatabase = new ConfigsDatabaseTestProvider(configsDslContext, configsFlyway).create(false); - val jobDatabase = new JobsDatabaseTestProvider(jobsDslContext, jobsFlyway).create(false); - val configRepository = new ConfigRepository(configDatabase); - val configsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val configDatabaseInitializer = DatabaseCheckFactory.createConfigsDatabaseInitializer(configsDslContext, - configsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.CONFIGS_INITIAL_SCHEMA_PATH)); - val configsDatabaseMigrator = new ConfigsDatabaseMigrator(configDatabase, configsFlyway); - final Optional definitionsProvider = - Optional.of(new LocalDefinitionsProvider()); - val jobsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val jobsDatabaseInitializer = DatabaseCheckFactory.createJobsDatabaseInitializer(jobsDslContext, - jobsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.JOBS_INITIAL_SCHEMA_PATH)); - val jobsDatabaseMigrator = new JobsDatabaseMigrator(jobDatabase, jobsFlyway); - val jobsPersistence = new DefaultJobPersistence(jobDatabase); - val protocolVersionChecker = new ProtocolVersionChecker(jobsPersistence, airbyteProtocolRange, configRepository, definitionsProvider); - val applyDefinitionsHelper = new ApplyDefinitionsHelper(configRepository, definitionsProvider, jobsPersistence); - val postLoadExecutor = new DefaultPostLoadExecutor(applyDefinitionsHelper, mockedFeatureFlags, jobsPersistence, mockedSecretMigrator); - - val bootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, mockedSecretMigrator, postLoadExecutor); - bootloader.load(); - - val jobsMigrator = new JobsDatabaseMigrator(jobDatabase, jobsFlyway); - assertEquals(CURRENT_JOBS_MIGRATION_VERSION, jobsMigrator.getLatestMigration().getVersion().getVersion()); - - val configsMigrator = new ConfigsDatabaseMigrator(configDatabase, configsFlyway); - assertEquals(CURRENT_CONFIGS_MIGRATION_VERSION, configsMigrator.getLatestMigration().getVersion().getVersion()); - - assertEquals(VERSION_0330_ALPHA, jobsPersistence.getVersion().get()); - assertEquals(new Version(PROTOCOL_VERSION_123), jobsPersistence.getAirbyteProtocolVersionMin().get()); - assertEquals(new Version(PROTOCOL_VERSION_124), jobsPersistence.getAirbyteProtocolVersionMax().get()); - - assertNotEquals(Optional.empty(), jobsPersistence.getDeployment()); - } - } - - @Test - void testBootloaderAppRunSecretMigration() throws Exception { - val mockedConfigs = mock(Configs.class); - when(mockedConfigs.getSecretPersistenceType()).thenReturn(TESTING_CONFIG_DB_TABLE); - - val currentAirbyteVersion = new AirbyteVersion(VERSION_0330_ALPHA); - val airbyteProtocolRange = new AirbyteProtocolVersionRange(new Version(PROTOCOL_VERSION_123), new Version(PROTOCOL_VERSION_124)); - val mockedFeatureFlags = mock(FeatureFlags.class); - val runMigrationOnStartup = true; - - try (val configsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES); - val jobsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES)) { - - val configsFlyway = createConfigsFlyway(configsDataSource); - val jobsFlyway = createJobsFlyway(jobsDataSource); - - val configDatabase = new ConfigsDatabaseTestProvider(configsDslContext, configsFlyway).create(false); - val jobDatabase = new JobsDatabaseTestProvider(jobsDslContext, jobsFlyway).create(false); - val configRepository = new ConfigRepository(configDatabase); - val configsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val configDatabaseInitializer = DatabaseCheckFactory.createConfigsDatabaseInitializer(configsDslContext, - configsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.CONFIGS_INITIAL_SCHEMA_PATH)); - val configsDatabaseMigrator = new ConfigsDatabaseMigrator(configDatabase, configsFlyway); - final Optional definitionsProvider = - Optional.of(new LocalDefinitionsProvider()); - val jobsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val jobsDatabaseInitializer = DatabaseCheckFactory.createJobsDatabaseInitializer(jobsDslContext, - jobsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.JOBS_INITIAL_SCHEMA_PATH)); - val jobsDatabaseMigrator = new JobsDatabaseMigrator(jobDatabase, jobsFlyway); - val jobsPersistence = new DefaultJobPersistence(jobDatabase); - val secretPersistence = new LocalTestingSecretPersistence(configDatabase); - val protocolVersionChecker = new ProtocolVersionChecker(jobsPersistence, airbyteProtocolRange, configRepository, definitionsProvider); - - val localTestingSecretPersistence = new LocalTestingSecretPersistence(configDatabase); - - val secretsReader = new SecretsRepositoryReader(configRepository, new RealSecretsHydrator(localTestingSecretPersistence)); - val secretsWriter = new SecretsRepositoryWriter(configRepository, Optional.of(secretPersistence), Optional.empty()); - - val spiedSecretMigrator = - spy(new SecretMigrator(secretsReader, secretsWriter, configRepository, jobsPersistence, Optional.of(secretPersistence))); - - val applyDefinitionsHelper = new ApplyDefinitionsHelper(configRepository, definitionsProvider, jobsPersistence); - var postLoadExecutor = new DefaultPostLoadExecutor(applyDefinitionsHelper, mockedFeatureFlags, jobsPersistence, null); - - // Bootstrap the database for the test - val initBootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, null, postLoadExecutor); - initBootloader.load(); - - final DefinitionsProvider localDefinitions = new LocalDefinitionsProvider(); - configRepository.seedActorDefinitions(localDefinitions.getSourceDefinitions(), localDefinitions.getDestinationDefinitions()); - - final String sourceSpecs = """ - { - "account_id": "1234567891234567", - "start_date": "2022-04-01T00:00:00Z", - "access_token": "nonhiddensecret", - "include_deleted": false, - "fetch_thumbnail_images": false - } - - """; - - final ObjectMapper mapper = new ObjectMapper(); - - final UUID workspaceId = UUID.randomUUID(); - configRepository.writeStandardWorkspaceNoSecrets(new StandardWorkspace() - .withWorkspaceId(workspaceId) - .withName("wName") - .withSlug("wSlug") - .withEmail("email@mail.com") - .withTombstone(false) - .withInitialSetupComplete(false) - .withDefaultGeography(Geography.AUTO)); - final UUID sourceId = UUID.randomUUID(); - configRepository.writeSourceConnectionNoSecrets(new SourceConnection() - .withSourceDefinitionId(UUID.fromString("e7778cfc-e97c-4458-9ecb-b4f2bba8946c")) // Facebook Marketing - .withSourceId(sourceId) - .withName("test source") - .withWorkspaceId(workspaceId) - .withTombstone(false) - .withConfiguration(mapper.readTree(sourceSpecs))); - - when(mockedFeatureFlags.forceSecretMigration()).thenReturn(false); - - postLoadExecutor = new DefaultPostLoadExecutor(applyDefinitionsHelper, mockedFeatureFlags, jobsPersistence, spiedSecretMigrator); - - // Perform secrets migration - var bootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, spiedSecretMigrator, postLoadExecutor); - boolean isMigrated = jobsPersistence.isSecretMigrated(); - - assertFalse(isMigrated); - - bootloader.load(); - verify(spiedSecretMigrator).migrateSecrets(); - - final SourceConnection sourceConnection = configRepository.getSourceConnection(sourceId); - - assertFalse(sourceConnection.getConfiguration().toString().contains("nonhiddensecret")); - assertTrue(sourceConnection.getConfiguration().toString().contains("_secret")); - - isMigrated = jobsPersistence.isSecretMigrated(); - assertTrue(isMigrated); - - // Verify that the migration does not happen if it has already been performed - reset(spiedSecretMigrator); - // We need to re-create the bootloader because it is closing the persistence after running load - bootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, spiedSecretMigrator, postLoadExecutor); - bootloader.load(); - verifyNoInteractions(spiedSecretMigrator); - - // Verify that the migration occurs if the force migration feature flag is enabled - reset(spiedSecretMigrator); - when(mockedFeatureFlags.forceSecretMigration()).thenReturn(true); - // We need to re-create the bootloader because it is closing the persistence after running load - bootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, spiedSecretMigrator, postLoadExecutor); - bootloader.load(); - verify(spiedSecretMigrator).migrateSecrets(); - } - } - - // - @Test - void testIsLegalUpgradePredicate() throws Exception { - val currentAirbyteVersion = new AirbyteVersion(VERSION_0330_ALPHA); - val airbyteProtocolRange = new AirbyteProtocolVersionRange(new Version(PROTOCOL_VERSION_123), new Version(PROTOCOL_VERSION_124)); - val mockedFeatureFlags = mock(FeatureFlags.class); - val runMigrationOnStartup = true; - val mockedSecretMigrator = mock(SecretMigrator.class); - - try (val configsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES); - val jobsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES)) { - - val configsFlyway = createConfigsFlyway(configsDataSource); - val jobsFlyway = createJobsFlyway(jobsDataSource); - - val configDatabase = new ConfigsDatabaseTestProvider(configsDslContext, configsFlyway).create(false); - val jobDatabase = new JobsDatabaseTestProvider(jobsDslContext, jobsFlyway).create(false); - val configRepository = new ConfigRepository(configDatabase); - val configsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val configDatabaseInitializer = DatabaseCheckFactory.createConfigsDatabaseInitializer(configsDslContext, - configsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.CONFIGS_INITIAL_SCHEMA_PATH)); - val configsDatabaseMigrator = new ConfigsDatabaseMigrator(configDatabase, configsFlyway); - final Optional definitionsProvider = Optional.of( - new LocalDefinitionsProvider()); - val jobsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val jobsDatabaseInitializer = DatabaseCheckFactory.createJobsDatabaseInitializer(jobsDslContext, - jobsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.JOBS_INITIAL_SCHEMA_PATH)); - val jobsDatabaseMigrator = new JobsDatabaseMigrator(jobDatabase, jobsFlyway); - val jobsPersistence = new DefaultJobPersistence(jobDatabase); - val protocolVersionChecker = new ProtocolVersionChecker(jobsPersistence, airbyteProtocolRange, configRepository, definitionsProvider); - val applyDefinitionsHelper = new ApplyDefinitionsHelper(configRepository, definitionsProvider, jobsPersistence); - val postLoadExecutor = - new DefaultPostLoadExecutor(applyDefinitionsHelper, mockedFeatureFlags, jobsPersistence, mockedSecretMigrator); - - val bootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, mockedSecretMigrator, postLoadExecutor); - - // starting from no previous version is always legal. - assertTrue(bootloader.isLegalUpgrade(null, new AirbyteVersion("0.17.1-alpha"))); - assertTrue(bootloader.isLegalUpgrade(null, new AirbyteVersion(VERSION_0320_ALPHA))); - assertTrue(bootloader.isLegalUpgrade(null, new AirbyteVersion(VERSION_0321_ALPHA))); - assertTrue(bootloader.isLegalUpgrade(null, new AirbyteVersion("0.33.1-alpha"))); - // starting from a version that is pre-breaking migration cannot go past the breaking migration. - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0170_ALPHA), new AirbyteVersion("0.17.1-alpha"))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0170_ALPHA), new AirbyteVersion("0.18.0-alpha"))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0170_ALPHA), new AirbyteVersion(VERSION_0320_ALPHA))); - assertFalse(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0170_ALPHA), new AirbyteVersion(VERSION_0321_ALPHA))); - assertFalse(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0170_ALPHA), new AirbyteVersion(VERSION_0330_ALPHA))); - // any migration starting at the breaking migration or after it can upgrade to anything. - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0320_ALPHA), new AirbyteVersion(VERSION_0321_ALPHA))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0320_ALPHA), new AirbyteVersion(VERSION_0330_ALPHA))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0321_ALPHA), new AirbyteVersion(VERSION_0321_ALPHA))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0321_ALPHA), new AirbyteVersion(VERSION_0330_ALPHA))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0330_ALPHA), new AirbyteVersion("0.33.1-alpha"))); - assertTrue(bootloader.isLegalUpgrade(new AirbyteVersion(VERSION_0330_ALPHA), new AirbyteVersion("0.34.0-alpha"))); - } - } - - @Test - void testPostLoadExecutionExecutes() throws Exception { - final var testTriggered = new AtomicBoolean(); - val currentAirbyteVersion = new AirbyteVersion(VERSION_0330_ALPHA); - val airbyteProtocolRange = new AirbyteProtocolVersionRange(new Version(PROTOCOL_VERSION_123), new Version(PROTOCOL_VERSION_124)); - val mockedFeatureFlags = mock(FeatureFlags.class); - val runMigrationOnStartup = true; - val mockedSecretMigrator = mock(SecretMigrator.class); - - try (val configsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES); - val jobsDslContext = DSLContextFactory.create(configsDataSource, SQLDialect.POSTGRES)) { - - val configsFlyway = createConfigsFlyway(configsDataSource); - val jobsFlyway = createJobsFlyway(jobsDataSource); - - val configDatabase = new ConfigsDatabaseTestProvider(configsDslContext, configsFlyway).create(false); - val jobDatabase = new JobsDatabaseTestProvider(jobsDslContext, jobsFlyway).create(false); - val configRepository = new ConfigRepository(configDatabase); - val configsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val configDatabaseInitializer = DatabaseCheckFactory.createConfigsDatabaseInitializer(configsDslContext, - configsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.CONFIGS_INITIAL_SCHEMA_PATH)); - val configsDatabaseMigrator = new ConfigsDatabaseMigrator(configDatabase, configsFlyway); - final Optional definitionsProvider = - Optional.of(new LocalDefinitionsProvider()); - val jobsDatabaseInitializationTimeoutMs = TimeUnit.SECONDS.toMillis(60L); - val jobsDatabaseInitializer = DatabaseCheckFactory.createJobsDatabaseInitializer(jobsDslContext, - jobsDatabaseInitializationTimeoutMs, MoreResources.readResource(DatabaseConstants.JOBS_INITIAL_SCHEMA_PATH)); - val jobsDatabaseMigrator = new JobsDatabaseMigrator(jobDatabase, jobsFlyway); - val jobsPersistence = new DefaultJobPersistence(jobDatabase); - val protocolVersionChecker = new ProtocolVersionChecker(jobsPersistence, airbyteProtocolRange, configRepository, definitionsProvider); - val postLoadExecutor = new PostLoadExecutor() { - - @Override - public void execute() { - testTriggered.set(true); - } - - }; - val bootloader = - new Bootloader(false, configRepository, configDatabaseInitializer, configsDatabaseMigrator, currentAirbyteVersion, - definitionsProvider, mockedFeatureFlags, jobsDatabaseInitializer, jobsDatabaseMigrator, jobsPersistence, protocolVersionChecker, - runMigrationOnStartup, mockedSecretMigrator, postLoadExecutor); - bootloader.load(); - assertTrue(testTriggered.get()); - } - } - - private Flyway createConfigsFlyway(final DataSource dataSource) { - return FlywayFactory.create(dataSource, getClass().getName(), ConfigsDatabaseMigrator.DB_IDENTIFIER, - ConfigsDatabaseMigrator.MIGRATION_FILE_LOCATION); - } - - private Flyway createJobsFlyway(final DataSource dataSource) { - return FlywayFactory.create(dataSource, getClass().getName(), JobsDatabaseMigrator.DB_IDENTIFIER, - JobsDatabaseMigrator.MIGRATION_FILE_LOCATION); - } - - private void closeDataSource(final DataSource dataSource) throws Exception { - DataSourceFactory.close(dataSource); - } - -} diff --git a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/DefaultPostLoadExecutorTest.java b/airbyte-bootloader/src/test/java/io/airbyte/bootloader/DefaultPostLoadExecutorTest.java deleted file mode 100644 index afeddba5533ac..0000000000000 --- a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/DefaultPostLoadExecutorTest.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.config.init.ApplyDefinitionsHelper; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -/** - * Test suite for the {@link DefaultPostLoadExecutor} class. - */ -class DefaultPostLoadExecutorTest { - - @ParameterizedTest - @CsvSource({"true,true,1", "true,false,1", "false,true,0", "false,false,1"}) - void testPostLoadExecution(final boolean forceSecretMigration, final boolean isSecretMigration, final int expectedTimes) - throws Exception { - final ApplyDefinitionsHelper applyDefinitionsHelper = mock(ApplyDefinitionsHelper.class); - final FeatureFlags featureFlags = mock(FeatureFlags.class); - final JobPersistence jobPersistence = mock(JobPersistence.class); - final SecretMigrator secretMigrator = mock(SecretMigrator.class); - - when(featureFlags.forceSecretMigration()).thenReturn(forceSecretMigration); - when(jobPersistence.isSecretMigrated()).thenReturn(isSecretMigration); - - final DefaultPostLoadExecutor postLoadExecution = - new DefaultPostLoadExecutor(applyDefinitionsHelper, featureFlags, jobPersistence, secretMigrator); - - assertDoesNotThrow(() -> postLoadExecution.execute()); - verify(applyDefinitionsHelper, times(1)).apply(); - verify(secretMigrator, times(expectedTimes)).migrateSecrets(); - } - - @Test - void testPostLoadExecutionNullSecretManager() throws JsonValidationException, IOException { - final ApplyDefinitionsHelper applyDefinitionsHelper = mock(ApplyDefinitionsHelper.class); - final FeatureFlags featureFlags = mock(FeatureFlags.class); - final JobPersistence jobPersistence = mock(JobPersistence.class); - - when(featureFlags.forceSecretMigration()).thenReturn(true); - - final DefaultPostLoadExecutor postLoadExecution = - new DefaultPostLoadExecutor(applyDefinitionsHelper, featureFlags, jobPersistence, null); - - assertDoesNotThrow(() -> postLoadExecution.execute()); - verify(applyDefinitionsHelper, times(1)).apply(); - } - - @Test - void testPostLoadExecutionWithException() throws JsonValidationException, IOException { - final ApplyDefinitionsHelper applyDefinitionsHelper = mock(ApplyDefinitionsHelper.class); - final FeatureFlags featureFlags = mock(FeatureFlags.class); - final JobPersistence jobPersistence = mock(JobPersistence.class); - final SecretMigrator secretMigrator = mock(SecretMigrator.class); - - doThrow(new IOException("test")).when(applyDefinitionsHelper).apply(); - - final DefaultPostLoadExecutor postLoadExecution = - new DefaultPostLoadExecutor(applyDefinitionsHelper, featureFlags, jobPersistence, secretMigrator); - - assertThrows(IOException.class, () -> postLoadExecution.execute()); - } - -} diff --git a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/ProtocolVersionCheckerTest.java b/airbyte-bootloader/src/test/java/io/airbyte/bootloader/ProtocolVersionCheckerTest.java deleted file mode 100644 index 8fe8e5b57eeda..0000000000000 --- a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/ProtocolVersionCheckerTest.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorType; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.init.DefinitionsProvider; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.protocol.models.ConnectorSpecification; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -class ProtocolVersionCheckerTest { - - ConfigRepository configRepository; - DefinitionsProvider definitionsProvider; - JobPersistence jobPersistence; - - final Version V0_0_0 = new Version("0.0.0"); - final Version V1_0_0 = new Version("1.0.0"); - final Version V2_0_0 = new Version("2.0.0"); - - @BeforeEach - void beforeEach() throws IOException { - configRepository = mock(ConfigRepository.class); - definitionsProvider = mock(DefinitionsProvider.class); - jobPersistence = mock(JobPersistence.class); - - when(jobPersistence.getVersion()).thenReturn(Optional.of("1.2.3")); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testFirstInstallCheck(final boolean supportAutoUpgrade) throws IOException { - final AirbyteProtocolVersionRange expectedRange = new AirbyteProtocolVersionRange(V0_0_0, V1_0_0); - when(jobPersistence.getVersion()).thenReturn(Optional.empty()); - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedRange, configRepository, Optional.of(definitionsProvider)); - final Optional supportedRange = protocolVersionChecker.validate(supportAutoUpgrade); - assertTrue(supportedRange.isPresent()); - assertEquals(expectedRange.max(), supportedRange.get().max()); - assertEquals(expectedRange.min(), supportedRange.get().min()); - } - - @Test - void testGetTargetRange() throws IOException { - final AirbyteProtocolVersionRange expectedRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedRange, configRepository, Optional.of(definitionsProvider)); - assertEquals(expectedRange.max(), protocolVersionChecker.getTargetProtocolVersionRange().max()); - assertEquals(expectedRange.min(), protocolVersionChecker.getTargetProtocolVersionRange().min()); - } - - @Test - void testRetrievingCurrentConflicts() throws IOException { - final AirbyteProtocolVersionRange targetRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final UUID source3 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V0_0_0), - source2, Map.entry(ActorType.SOURCE, V1_0_0), - source3, Map.entry(ActorType.SOURCE, V2_0_0), - dest1, Map.entry(ActorType.DESTINATION, V0_0_0), - dest2, Map.entry(ActorType.DESTINATION, V0_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, targetRange, configRepository, Optional.of(definitionsProvider)); - final Map> conflicts = protocolVersionChecker.getConflictingActorDefinitions(targetRange); - - final Map> expectedConflicts = Map.of( - ActorType.DESTINATION, Set.of(dest1, dest2), - ActorType.SOURCE, Set.of(source1)); - assertEquals(expectedConflicts, conflicts); - } - - @Test - void testRetrievingCurrentConflictsWhenNoConflicts() throws IOException { - final AirbyteProtocolVersionRange targetRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - - final UUID source1 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V2_0_0), - dest1, Map.entry(ActorType.DESTINATION, V1_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, targetRange, configRepository, Optional.of(definitionsProvider)); - final Map> conflicts = protocolVersionChecker.getConflictingActorDefinitions(targetRange); - - assertEquals(Map.of(), conflicts); - } - - @Test - void testProjectRemainingSourceConflicts() { - final AirbyteProtocolVersionRange targetRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - - final UUID unrelatedSource = UUID.randomUUID(); - final UUID upgradedSource = UUID.randomUUID(); - final UUID notChangedSource = UUID.randomUUID(); - final UUID missingSource = UUID.randomUUID(); - final Set initialConflicts = Set.of(upgradedSource, notChangedSource, missingSource); - - setNewSourceDefinitions(List.of( - Map.entry(unrelatedSource, V2_0_0), - Map.entry(upgradedSource, V1_0_0), - Map.entry(notChangedSource, V0_0_0))); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, targetRange, configRepository, Optional.of(definitionsProvider)); - final Set actualConflicts = - protocolVersionChecker.projectRemainingConflictsAfterConnectorUpgrades(targetRange, initialConflicts, ActorType.SOURCE); - - final Set expectedConflicts = Set.of(notChangedSource, missingSource); - assertEquals(expectedConflicts, actualConflicts); - } - - @Test - void testProjectRemainingDestinationConflicts() { - final AirbyteProtocolVersionRange targetRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - final UUID dest3 = UUID.randomUUID(); - final Set initialConflicts = Set.of(dest1, dest2, dest3); - - setNewDestinationDefinitions(List.of( - Map.entry(dest1, V2_0_0), - Map.entry(dest2, V1_0_0), - Map.entry(dest3, V2_0_0))); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, targetRange, configRepository, Optional.of(definitionsProvider)); - final Set actualConflicts = - protocolVersionChecker.projectRemainingConflictsAfterConnectorUpgrades(targetRange, initialConflicts, ActorType.DESTINATION); - - final Set expectedConflicts = Set.of(); - assertEquals(expectedConflicts, actualConflicts); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testValidateSameRange(final boolean supportAutoUpgrade) throws Exception { - final AirbyteProtocolVersionRange expectedRange = new AirbyteProtocolVersionRange(V0_0_0, V2_0_0); - setCurrentProtocolRangeRange(expectedRange.min(), expectedRange.max()); - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedRange, configRepository, Optional.of(definitionsProvider)); - - final Optional supportedRange = protocolVersionChecker.validate(supportAutoUpgrade); - assertTrue(supportedRange.isPresent()); - assertEquals(expectedRange.max(), supportedRange.get().max()); - assertEquals(expectedRange.min(), supportedRange.get().min()); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testValidateAllConnectorsAreUpgraded(final boolean supportAutoUpgrade) throws Exception { - setCurrentProtocolRangeRange(V0_0_0, V1_0_0); - - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final UUID source3 = UUID.randomUUID(); - final UUID source4 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - final UUID dest3 = UUID.randomUUID(); - final AirbyteProtocolVersionRange expectedTargetVersionRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V0_0_0), - source2, Map.entry(ActorType.SOURCE, V1_0_0), - source3, Map.entry(ActorType.SOURCE, V0_0_0), - source4, Map.entry(ActorType.SOURCE, V0_0_0), - dest1, Map.entry(ActorType.DESTINATION, V0_0_0), - dest2, Map.entry(ActorType.DESTINATION, V1_0_0), - dest3, Map.entry(ActorType.DESTINATION, V2_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - setNewSourceDefinitions(List.of( - Map.entry(source1, V1_0_0), - Map.entry(source2, V1_0_0), - Map.entry(source3, V2_0_0), - Map.entry(source4, V1_0_0))); - setNewDestinationDefinitions(List.of( - Map.entry(dest1, V1_0_0), - Map.entry(dest2, V1_0_0), - Map.entry(dest3, V2_0_0))); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedTargetVersionRange, configRepository, Optional.of(definitionsProvider)); - final Optional actualRange = protocolVersionChecker.validate(supportAutoUpgrade); - - // Without auto upgrade, we will fail the validation because it would require connector automatic - // actor definition - // upgrade for used sources/destinations. - if (supportAutoUpgrade) { - assertTrue(actualRange.isPresent()); - assertEquals(expectedTargetVersionRange.max(), actualRange.get().max()); - assertEquals(expectedTargetVersionRange.min(), actualRange.get().min()); - } else { - assertEquals(Optional.empty(), actualRange); - } - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testValidateBadUpgradeMissingSource(final boolean supportAutoUpgrade) throws Exception { - final AirbyteProtocolVersionRange expectedTargetVersionRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - setCurrentProtocolRangeRange(V0_0_0, V1_0_0); - - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V0_0_0), - source2, Map.entry(ActorType.SOURCE, V0_0_0), - dest1, Map.entry(ActorType.DESTINATION, V0_0_0), - dest2, Map.entry(ActorType.DESTINATION, V0_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - setNewSourceDefinitions(List.of( - Map.entry(source1, V0_0_0), - Map.entry(source2, V1_0_0))); - setNewDestinationDefinitions(List.of( - Map.entry(dest1, V1_0_0), - Map.entry(dest2, V1_0_0))); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedTargetVersionRange, configRepository, Optional.of(definitionsProvider)); - final Optional actualRange = protocolVersionChecker.validate(supportAutoUpgrade); - assertEquals(Optional.empty(), actualRange); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testValidateBadUpgradeMissingDestination(final boolean supportAutoUpgrade) throws Exception { - final AirbyteProtocolVersionRange expectedTargetVersionRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - setCurrentProtocolRangeRange(V0_0_0, V1_0_0); - - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V0_0_0), - source2, Map.entry(ActorType.SOURCE, V0_0_0), - dest1, Map.entry(ActorType.DESTINATION, V0_0_0), - dest2, Map.entry(ActorType.DESTINATION, V0_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - setNewSourceDefinitions(List.of( - Map.entry(source1, V1_0_0), - Map.entry(source2, V1_0_0))); - setNewDestinationDefinitions(List.of( - Map.entry(dest1, V1_0_0), - Map.entry(dest2, V0_0_0))); - - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedTargetVersionRange, configRepository, Optional.of(definitionsProvider)); - final Optional actualRange = protocolVersionChecker.validate(supportAutoUpgrade); - assertEquals(Optional.empty(), actualRange); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testValidateFailsOnProtocolRangeChangeWithoutDefinitionsProvider(final boolean supportAutoUpgrade) throws Exception { - final AirbyteProtocolVersionRange expectedTargetVersionRange = new AirbyteProtocolVersionRange(V1_0_0, V2_0_0); - setCurrentProtocolRangeRange(V0_0_0, V1_0_0); - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedTargetVersionRange, configRepository, Optional.empty()); - - final UUID source1 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V0_0_0), - dest1, Map.entry(ActorType.DESTINATION, V0_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - final Optional actualRange = protocolVersionChecker.validate(supportAutoUpgrade); - assertEquals(Optional.empty(), actualRange); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void testValidateSucceedsWhenNoProtocolRangeChangeWithoutDefinitionsProvider(final boolean supportAutoUpgrade) throws Exception { - final AirbyteProtocolVersionRange expectedTargetVersionRange = new AirbyteProtocolVersionRange(V0_0_0, V2_0_0); - setCurrentProtocolRangeRange(V0_0_0, V2_0_0); - final ProtocolVersionChecker protocolVersionChecker = - new ProtocolVersionChecker(jobPersistence, expectedTargetVersionRange, configRepository, Optional.empty()); - - final UUID source1 = UUID.randomUUID(); - final UUID dest1 = UUID.randomUUID(); - - final Map> initialActorDefinitions = Map.of( - source1, Map.entry(ActorType.SOURCE, V0_0_0), - dest1, Map.entry(ActorType.DESTINATION, V0_0_0)); - when(configRepository.getActorDefinitionToProtocolVersionMap()).thenReturn(initialActorDefinitions); - - final Optional actualRange = protocolVersionChecker.validate(supportAutoUpgrade); - assertTrue(actualRange.isPresent()); - assertEquals(expectedTargetVersionRange.max(), actualRange.get().max()); - assertEquals(expectedTargetVersionRange.min(), actualRange.get().min()); - } - - private void setCurrentProtocolRangeRange(final Version min, final Version max) throws IOException { - when(jobPersistence.getCurrentProtocolVersionRange()).thenReturn(Optional.of(new AirbyteProtocolVersionRange(min, max))); - when(jobPersistence.getAirbyteProtocolVersionMin()).thenReturn(Optional.of(min)); - when(jobPersistence.getAirbyteProtocolVersionMax()).thenReturn(Optional.of(max)); - } - - private void setNewDestinationDefinitions(final List> defs) { - final List destDefinitions = defs.stream() - .map(e -> new StandardDestinationDefinition() - .withDestinationDefinitionId(e.getKey()) - .withSpec(new ConnectorSpecification().withProtocolVersion(e.getValue().serialize()))) - .toList(); - when(definitionsProvider.getDestinationDefinitions()).thenReturn(destDefinitions); - } - - private void setNewSourceDefinitions(final List> defs) { - final List sourceDefinitions = defs.stream() - .map(e -> new StandardSourceDefinition() - .withSourceDefinitionId(e.getKey()) - .withSpec(new ConnectorSpecification().withProtocolVersion(e.getValue().serialize()))) - .toList(); - when(definitionsProvider.getSourceDefinitions()).thenReturn(sourceDefinitions); - } - -} diff --git a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/SecretMigratorTest.java b/airbyte-bootloader/src/test/java/io/airbyte/bootloader/SecretMigratorTest.java deleted file mode 100644 index 7fd6a4be3519c..0000000000000 --- a/airbyte-bootloader/src/test/java/io/airbyte/bootloader/SecretMigratorTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.bootloader; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.Lists; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class SecretMigratorTest { - - private final UUID workspaceId = UUID.randomUUID(); - - @Mock - private ConfigRepository configRepository; - - @Mock - private SecretsRepositoryReader secretsReader; - - @Mock - private SecretsRepositoryWriter secretsWriter; - - @Mock - private SecretPersistence secretPersistence; - - @Mock - private JobPersistence jobPersistence; - - private SecretMigrator secretMigrator; - - @BeforeEach - void setup() { - secretMigrator = Mockito.spy(new SecretMigrator(secretsReader, secretsWriter, configRepository, jobPersistence, Optional.of(secretPersistence))); - } - - @Test - void testMigrateSecret() throws Exception { - final JsonNode sourceSpec = Jsons.jsonNode("sourceSpec"); - final UUID sourceDefinitionId = UUID.randomUUID(); - final StandardSourceDefinition standardSourceDefinition = new StandardSourceDefinition() - .withSourceDefinitionId(sourceDefinitionId) - .withSpec( - new ConnectorSpecification() - .withConnectionSpecification(sourceSpec)); - final Map standardSourceDefinitions = new HashMap<>(); - standardSourceDefinitions.put(sourceDefinitionId, standardSourceDefinition.getSpec()); - when(configRepository.listStandardSourceDefinitions(true)) - .thenReturn(Lists.newArrayList(standardSourceDefinition)); - - final JsonNode sourceConfiguration = Jsons.jsonNode("sourceConfiguration"); - final SourceConnection sourceConnection = new SourceConnection() - .withSourceId(UUID.randomUUID()) - .withSourceDefinitionId(sourceDefinitionId) - .withConfiguration(sourceConfiguration) - .withWorkspaceId(workspaceId); - final List sourceConnections = Lists.newArrayList(sourceConnection); - when(configRepository.listSourceConnection()) - .thenReturn(sourceConnections); - - final JsonNode destinationSpec = Jsons.jsonNode("destinationSpec"); - final UUID destinationDefinitionId = UUID.randomUUID(); - final StandardDestinationDefinition standardDestinationDefinition = new StandardDestinationDefinition() - .withDestinationDefinitionId(destinationDefinitionId) - .withSpec( - new ConnectorSpecification() - .withConnectionSpecification(destinationSpec)); - final Map standardDestinationDefinitions = new HashMap<>(); - standardDestinationDefinitions.put(destinationDefinitionId, standardDestinationDefinition.getSpec()); - when(configRepository.listStandardDestinationDefinitions(true)) - .thenReturn(Lists.newArrayList(standardDestinationDefinition)); - - final JsonNode destinationConfiguration = Jsons.jsonNode("destinationConfiguration"); - final DestinationConnection destinationConnection = new DestinationConnection() - .withDestinationId(UUID.randomUUID()) - .withDestinationDefinitionId(destinationDefinitionId) - .withConfiguration(destinationConfiguration) - .withWorkspaceId(workspaceId); - final List destinationConnections = Lists.newArrayList(destinationConnection); - when(configRepository.listDestinationConnection()) - .thenReturn(destinationConnections); - - when(secretsReader.getSourceConnectionWithSecrets(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(secretsReader.getDestinationConnectionWithSecrets(destinationConnection.getDestinationId())).thenReturn(destinationConnection); - - secretMigrator.migrateSecrets(); - - Mockito.verify(secretMigrator).migrateSources(sourceConnections, standardSourceDefinitions); - Mockito.verify(secretsWriter).writeSourceConnection(sourceConnection, standardSourceDefinition.getSpec()); - secretPersistence.write(any(), any()); - Mockito.verify(secretMigrator).migrateDestinations(destinationConnections, standardDestinationDefinitions); - Mockito.verify(secretsWriter).writeDestinationConnection(destinationConnection, standardDestinationDefinition.getSpec()); - - Mockito.verify(jobPersistence).setSecretMigrationDone(); - } - - @Test - void testSourceMigration() throws JsonValidationException, IOException { - final UUID definitionId1 = UUID.randomUUID(); - final UUID definitionId2 = UUID.randomUUID(); - final UUID sourceId1 = UUID.randomUUID(); - final UUID sourceId2 = UUID.randomUUID(); - final JsonNode sourceConfiguration1 = Jsons.jsonNode("conf1"); - final JsonNode sourceConfiguration2 = Jsons.jsonNode("conf2"); - final ConnectorSpecification sourceDefinition1 = new ConnectorSpecification().withConnectionSpecification(Jsons.jsonNode("def1")); - final ConnectorSpecification sourceDefinition2 = new ConnectorSpecification().withConnectionSpecification(Jsons.jsonNode("def2")); - final SourceConnection sourceConnection1 = new SourceConnection() - .withSourceId(sourceId1) - .withSourceDefinitionId(definitionId1) - .withConfiguration(sourceConfiguration1); - final SourceConnection sourceConnection2 = new SourceConnection() - .withSourceId(sourceId2) - .withSourceDefinitionId(definitionId2) - .withConfiguration(sourceConfiguration2); - - final List sources = Lists.newArrayList(sourceConnection1, sourceConnection2); - final Map definitionIdToDestinationSpecs = new HashMap<>(); - definitionIdToDestinationSpecs.put(definitionId1, sourceDefinition1); - definitionIdToDestinationSpecs.put(definitionId2, sourceDefinition2); - - secretMigrator.migrateSources(sources, definitionIdToDestinationSpecs); - - Mockito.verify(secretsWriter).writeSourceConnection(sourceConnection1, sourceDefinition1); - Mockito.verify(secretsWriter).writeSourceConnection(sourceConnection2, sourceDefinition2); - } - - @Test - void testDestinationMigration() throws JsonValidationException, IOException { - final UUID definitionId1 = UUID.randomUUID(); - final UUID definitionId2 = UUID.randomUUID(); - final UUID destinationId1 = UUID.randomUUID(); - final UUID destinationId2 = UUID.randomUUID(); - final JsonNode destinationConfiguration1 = Jsons.jsonNode("conf1"); - final JsonNode destinationConfiguration2 = Jsons.jsonNode("conf2"); - final ConnectorSpecification destinationDefinition1 = new ConnectorSpecification().withConnectionSpecification(Jsons.jsonNode("def1")); - final ConnectorSpecification destinationDefinition2 = new ConnectorSpecification().withConnectionSpecification(Jsons.jsonNode("def2")); - final DestinationConnection destinationConnection1 = new DestinationConnection() - .withDestinationId(destinationId1) - .withDestinationDefinitionId(definitionId1) - .withConfiguration(destinationConfiguration1); - final DestinationConnection destinationConnection2 = new DestinationConnection() - .withDestinationId(destinationId2) - .withDestinationDefinitionId(definitionId2) - .withConfiguration(destinationConfiguration2); - - final List destinations = Lists.newArrayList(destinationConnection1, destinationConnection2); - final Map definitionIdToDestinationSpecs = new HashMap<>(); - definitionIdToDestinationSpecs.put(definitionId1, destinationDefinition1); - definitionIdToDestinationSpecs.put(definitionId2, destinationDefinition2); - - secretMigrator.migrateDestinations(destinations, definitionIdToDestinationSpecs); - - Mockito.verify(secretsWriter).writeDestinationConnection(destinationConnection1, destinationDefinition1); - Mockito.verify(secretsWriter).writeDestinationConnection(destinationConnection2, destinationDefinition2); - } - -} diff --git a/airbyte-commons-server/build.gradle b/airbyte-commons-server/build.gradle deleted file mode 100644 index ec25c650ae7a6..0000000000000 --- a/airbyte-commons-server/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -plugins { - id "java-library" -} - -dependencies { - annotationProcessor platform(libs.micronaut.bom) - annotationProcessor libs.bundles.micronaut.annotation.processor - annotationProcessor libs.micronaut.jaxrs.processor - - implementation platform(libs.micronaut.bom) - implementation libs.bundles.micronaut - implementation libs.micronaut.jaxrs.server - - // Ensure that the versions defined in deps.toml are used - // instead of versions from transitive dependencies - implementation(libs.flyway.core) { - force = true - } - implementation(libs.s3) { - // Force to avoid updated version brought in transitively from Micronaut 3.8+ - // that is incompatible with our current Helm setup - force = true - } - implementation(libs.aws.java.sdk.s3) { - // Force to avoid updated version brought in transitively from Micronaut 3.8+ - // that is incompatible with our current Helm setup - force = true - } - - implementation project(':airbyte-analytics') - implementation project(':airbyte-api') - implementation project(':airbyte-commons-temporal') - implementation project(':airbyte-commons-worker') - implementation project(':airbyte-config:init') - implementation project(':airbyte-config:config-models') - implementation project(':airbyte-config:config-persistence') - implementation project(':airbyte-config:specs') - implementation project(':airbyte-metrics:metrics-lib') - implementation project(':airbyte-db:db-lib') - implementation project(":airbyte-json-validation") - implementation project(':airbyte-oauth') - implementation libs.airbyte.protocol - implementation project(':airbyte-persistence:job-persistence') - - implementation 'com.github.slugify:slugify:2.4' - implementation 'commons-cli:commons-cli:1.4' - implementation libs.temporal.sdk - implementation 'org.apache.cxf:cxf-core:3.4.2' - implementation 'org.eclipse.jetty:jetty-server:9.4.31.v20200723' - implementation 'org.eclipse.jetty:jetty-servlet:9.4.31.v20200723' - implementation 'org.glassfish.jaxb:jaxb-runtime:3.0.2' - implementation 'org.glassfish.jersey.containers:jersey-container-servlet' - implementation 'org.glassfish.jersey.inject:jersey-hk2' - implementation 'org.glassfish.jersey.media:jersey-media-json-jackson' - implementation 'org.glassfish.jersey.ext:jersey-bean-validation' - implementation 'org.quartz-scheduler:quartz:2.3.2' - implementation 'io.sentry:sentry:6.3.1' - implementation 'io.swagger:swagger-annotations:1.6.2' - - testImplementation project(':airbyte-test-utils') - testImplementation libs.postgresql - testImplementation libs.platform.testcontainers.postgresql - testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.1' - testImplementation 'org.mockito:mockito-inline:4.7.0' -} - -Task publishArtifactsTask = getPublishArtifactsTask("$rootProject.ext.version", project) diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/RequestLogger.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/RequestLogger.java deleted file mode 100644 index 67af0fe678203..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/RequestLogger.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.commons.json.Jsons; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.core.Context; -import org.apache.commons.io.IOUtils; -import org.eclipse.jetty.http.HttpStatus; -import org.glassfish.jersey.message.MessageUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -/** - * This class implements two {@code filter()} methods that execute as part of the Jersey framework - * request/response chain. - *

- * The first {@code filter()} is the Request Filter. It takes an incoming - * {@link ContainerRequestContext} that contains request information, such as the request body. In - * this filter, we extract the request body and store it back on the request context as a custom - * property. We don't write any logs for requests. However, since we want to include the request - * body in logs for responses, we have to extract the request body in this filter. - *

- * The second @{code filter()} is the Response Filter. It takes an incoming - * {@link ContainerResponseContext} that contains response information, such as the status code. - * This method also has read-only access to the original {@link ContainerRequestContext}, where we - * set the request body as a custom property in the request filter. This is where we create and - * persist log lines that contain both the response status code and the original request body. - */ -public class RequestLogger implements ContainerRequestFilter, ContainerResponseFilter { - - private static final Logger LOGGER = LoggerFactory.getLogger(RequestLogger.class); - private static final String REQUEST_BODY_PROPERTY = "requestBodyProperty"; - - @Context - private HttpServletRequest servletRequest; - - private final Map mdc; - - public RequestLogger(final Map mdc) { - this.mdc = mdc; - } - - @VisibleForTesting - RequestLogger(final Map mdc, final HttpServletRequest servletRequest) { - this.mdc = mdc; - this.servletRequest = servletRequest; - } - - @Override - public void filter(final ContainerRequestContext requestContext) throws IOException { - if ("POST".equals(requestContext.getMethod())) { - // hack to refill the entity stream so it doesn't interfere with other operations - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - IOUtils.copy(requestContext.getEntityStream(), baos); - final InputStream entity = new ByteArrayInputStream(baos.toByteArray()); - requestContext.setEntityStream(new ByteArrayInputStream(baos.toByteArray())); - // end hack - - requestContext.setProperty(REQUEST_BODY_PROPERTY, IOUtils.toString(entity, MessageUtils.getCharset(requestContext.getMediaType()))); - } - } - - @Override - public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) { - MDC.setContextMap(mdc); - - final String remoteAddr = servletRequest.getRemoteAddr(); - final String method = servletRequest.getMethod(); - final String url = servletRequest.getRequestURI(); - - final String requestBody = (String) requestContext.getProperty(REQUEST_BODY_PROPERTY); - - final boolean isPrintable = servletRequest.getHeader("Content-Type") != null && - servletRequest.getHeader("Content-Type").toLowerCase().contains("application/json") && - isValidJson(requestBody); - - final int status = responseContext.getStatus(); - - final StringBuilder logBuilder = createLogPrefix( - remoteAddr, - method, - status, - url); - - if (method.equals("POST") && requestBody != null && !requestBody.equals("") && isPrintable) { - logBuilder - .append(" - ") - .append(redactSensitiveInfo(requestBody)); - } - - if (HttpStatus.isClientError(status) || HttpStatus.isServerError(status)) { - LOGGER.error(logBuilder.toString()); - } else { - LOGGER.info(logBuilder.toString()); - } - } - - @VisibleForTesting - static StringBuilder createLogPrefix( - final String remoteAddr, - final String method, - final int status, - final String url) { - return new StringBuilder() - .append("REQ ") - .append(remoteAddr) - .append(" ") - .append(method) - .append(" ") - .append(status) - .append(" ") - .append(url); - } - - private static final Set TOP_LEVEL_SENSITIVE_FIELDS = Set.of( - "connectionConfiguration"); - - private static String redactSensitiveInfo(final String requestBody) { - final Optional jsonNodeOpt = Jsons.tryDeserialize(requestBody); - - if (jsonNodeOpt.isPresent()) { - final JsonNode jsonNode = jsonNodeOpt.get(); - if (jsonNode instanceof ObjectNode) { - final ObjectNode objectNode = (ObjectNode) jsonNode; - - for (final String topLevelSensitiveField : TOP_LEVEL_SENSITIVE_FIELDS) { - if (objectNode.has(topLevelSensitiveField)) { - objectNode.put(topLevelSensitiveField, "REDACTED"); - } - } - - return objectNode.toString(); - } else { - return "Unable to deserialize POST body for logging."; - } - } - - return requestBody; - } - - private static boolean isValidJson(final String json) { - return Jsons.tryDeserialize(json).isPresent(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/ServerConstants.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/ServerConstants.java deleted file mode 100644 index 6bff247a533c2..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/ServerConstants.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server; - -public class ServerConstants { - - public static final String DEV_IMAGE_TAG = "dev"; - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ApiPojoConverters.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ApiPojoConverters.java deleted file mode 100644 index 2f2b73d8b66b3..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ApiPojoConverters.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import io.airbyte.api.model.generated.ActorDefinitionResourceRequirements; -import io.airbyte.api.model.generated.AttemptSyncConfig; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionSchedule; -import io.airbyte.api.model.generated.ConnectionScheduleData; -import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; -import io.airbyte.api.model.generated.ConnectionScheduleDataCron; -import io.airbyte.api.model.generated.ConnectionState; -import io.airbyte.api.model.generated.ConnectionStateType; -import io.airbyte.api.model.generated.ConnectionStatus; -import io.airbyte.api.model.generated.Geography; -import io.airbyte.api.model.generated.JobType; -import io.airbyte.api.model.generated.JobTypeResourceLimit; -import io.airbyte.api.model.generated.NonBreakingChangesPreference; -import io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig; -import io.airbyte.api.model.generated.ResourceRequirements; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.config.BasicSchedule; -import io.airbyte.config.Schedule; -import io.airbyte.config.StandardSync; -import io.airbyte.config.State; -import io.airbyte.config.StateWrapper; -import io.airbyte.config.helpers.StateMessageHelper; -import io.airbyte.workers.helper.StateConverter; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; - -public class ApiPojoConverters { - - public static io.airbyte.config.ActorDefinitionResourceRequirements actorDefResourceReqsToInternal(final ActorDefinitionResourceRequirements actorDefResourceReqs) { - if (actorDefResourceReqs == null) { - return null; - } - - return new io.airbyte.config.ActorDefinitionResourceRequirements() - .withDefault(actorDefResourceReqs.getDefault() == null ? null : resourceRequirementsToInternal(actorDefResourceReqs.getDefault())) - .withJobSpecific(actorDefResourceReqs.getJobSpecific() == null ? null - : actorDefResourceReqs.getJobSpecific() - .stream() - .map(jobSpecific -> new io.airbyte.config.JobTypeResourceLimit() - .withJobType(toInternalJobType(jobSpecific.getJobType())) - .withResourceRequirements(resourceRequirementsToInternal(jobSpecific.getResourceRequirements()))) - .collect(Collectors.toList())); - } - - public static io.airbyte.config.AttemptSyncConfig attemptSyncConfigToInternal(final AttemptSyncConfig attemptSyncConfig) { - if (attemptSyncConfig == null) { - return null; - } - - final io.airbyte.config.AttemptSyncConfig internalAttemptSyncConfig = new io.airbyte.config.AttemptSyncConfig() - .withSourceConfiguration(attemptSyncConfig.getSourceConfiguration()) - .withDestinationConfiguration(attemptSyncConfig.getDestinationConfiguration()); - - final ConnectionState connectionState = attemptSyncConfig.getState(); - if (connectionState != null && connectionState.getStateType() != ConnectionStateType.NOT_SET) { - final StateWrapper stateWrapper = StateConverter.toInternal(attemptSyncConfig.getState()); - final io.airbyte.config.State state = StateMessageHelper.getState(stateWrapper); - internalAttemptSyncConfig.setState(state); - } - - return internalAttemptSyncConfig; - } - - public static io.airbyte.api.client.model.generated.AttemptSyncConfig attemptSyncConfigToClient(final io.airbyte.config.AttemptSyncConfig attemptSyncConfig, - final UUID connectionId, - final boolean useStreamCapableState) { - if (attemptSyncConfig == null) { - return null; - } - - final State state = attemptSyncConfig.getState(); - final Optional optStateWrapper = state != null ? StateMessageHelper.getTypedState( - state.getState(), useStreamCapableState) : Optional.empty(); - - return new io.airbyte.api.client.model.generated.AttemptSyncConfig() - .sourceConfiguration(attemptSyncConfig.getSourceConfiguration()) - .destinationConfiguration(attemptSyncConfig.getDestinationConfiguration()) - .state(StateConverter.toClient(connectionId, optStateWrapper.orElse(null))); - } - - public static ActorDefinitionResourceRequirements actorDefResourceReqsToApi(final io.airbyte.config.ActorDefinitionResourceRequirements actorDefResourceReqs) { - if (actorDefResourceReqs == null) { - return null; - } - - return new ActorDefinitionResourceRequirements() - ._default(actorDefResourceReqs.getDefault() == null ? null : resourceRequirementsToApi(actorDefResourceReqs.getDefault())) - .jobSpecific(actorDefResourceReqs.getJobSpecific() == null ? null - : actorDefResourceReqs.getJobSpecific() - .stream() - .map(jobSpecific -> new JobTypeResourceLimit() - .jobType(toApiJobType(jobSpecific.getJobType())) - .resourceRequirements(resourceRequirementsToApi(jobSpecific.getResourceRequirements()))) - .collect(Collectors.toList())); - } - - public static io.airbyte.config.ResourceRequirements resourceRequirementsToInternal(final ResourceRequirements resourceReqs) { - if (resourceReqs == null) { - return null; - } - - return new io.airbyte.config.ResourceRequirements() - .withCpuRequest(resourceReqs.getCpuRequest()) - .withCpuLimit(resourceReqs.getCpuLimit()) - .withMemoryRequest(resourceReqs.getMemoryRequest()) - .withMemoryLimit(resourceReqs.getMemoryLimit()); - } - - public static ResourceRequirements resourceRequirementsToApi(final io.airbyte.config.ResourceRequirements resourceReqs) { - if (resourceReqs == null) { - return null; - } - - return new ResourceRequirements() - .cpuRequest(resourceReqs.getCpuRequest()) - .cpuLimit(resourceReqs.getCpuLimit()) - .memoryRequest(resourceReqs.getMemoryRequest()) - .memoryLimit(resourceReqs.getMemoryLimit()); - } - - public static NormalizationDestinationDefinitionConfig normalizationDestinationDefinitionConfigToApi(final io.airbyte.config.NormalizationDestinationDefinitionConfig normalizationDestinationDefinitionConfig) { - if (normalizationDestinationDefinitionConfig == null) { - return new NormalizationDestinationDefinitionConfig().supported(false); - } - return new NormalizationDestinationDefinitionConfig() - .supported(true) - .normalizationRepository(normalizationDestinationDefinitionConfig.getNormalizationRepository()) - .normalizationTag(normalizationDestinationDefinitionConfig.getNormalizationTag()) - .normalizationIntegrationType(normalizationDestinationDefinitionConfig.getNormalizationIntegrationType()); - } - - public static ConnectionRead internalToConnectionRead(final StandardSync standardSync) { - final ConnectionRead connectionRead = new ConnectionRead() - .connectionId(standardSync.getConnectionId()) - .sourceId(standardSync.getSourceId()) - .destinationId(standardSync.getDestinationId()) - .operationIds(standardSync.getOperationIds()) - .status(toApiStatus(standardSync.getStatus())) - .name(standardSync.getName()) - .namespaceDefinition(Enums.convertTo(standardSync.getNamespaceDefinition(), io.airbyte.api.model.generated.NamespaceDefinitionType.class)) - .namespaceFormat(standardSync.getNamespaceFormat()) - .prefix(standardSync.getPrefix()) - .syncCatalog(CatalogConverter.toApi(standardSync.getCatalog(), standardSync.getFieldSelectionData())) - .sourceCatalogId(standardSync.getSourceCatalogId()) - .breakingChange(standardSync.getBreakingChange()) - .geography(Enums.convertTo(standardSync.getGeography(), Geography.class)) - .nonBreakingChangesPreference(Enums.convertTo(standardSync.getNonBreakingChangesPreference(), NonBreakingChangesPreference.class)) - .notifySchemaChanges(standardSync.getNotifySchemaChanges()); - - if (standardSync.getResourceRequirements() != null) { - connectionRead.resourceRequirements(resourceRequirementsToApi(standardSync.getResourceRequirements())); - } - - populateConnectionReadSchedule(standardSync, connectionRead); - - return connectionRead; - } - - public static JobType toApiJobType(final io.airbyte.config.JobTypeResourceLimit.JobType jobType) { - return Enums.convertTo(jobType, JobType.class); - } - - public static io.airbyte.config.JobTypeResourceLimit.JobType toInternalJobType(final JobType jobType) { - return Enums.convertTo(jobType, io.airbyte.config.JobTypeResourceLimit.JobType.class); - } - - // TODO(https://github.com/airbytehq/airbyte/issues/11432): remove these helpers. - public static ConnectionSchedule.TimeUnitEnum toApiTimeUnit(final Schedule.TimeUnit apiTimeUnit) { - return Enums.convertTo(apiTimeUnit, ConnectionSchedule.TimeUnitEnum.class); - } - - public static ConnectionSchedule.TimeUnitEnum toApiTimeUnit(final BasicSchedule.TimeUnit timeUnit) { - return Enums.convertTo(timeUnit, ConnectionSchedule.TimeUnitEnum.class); - } - - public static ConnectionStatus toApiStatus(final StandardSync.Status status) { - return Enums.convertTo(status, ConnectionStatus.class); - } - - public static StandardSync.Status toPersistenceStatus(final ConnectionStatus apiStatus) { - return Enums.convertTo(apiStatus, StandardSync.Status.class); - } - - public static StandardSync.NonBreakingChangesPreference toPersistenceNonBreakingChangesPreference(final NonBreakingChangesPreference preference) { - return Enums.convertTo(preference, StandardSync.NonBreakingChangesPreference.class); - } - - public static Geography toApiGeography(final io.airbyte.config.Geography geography) { - return Enums.convertTo(geography, Geography.class); - } - - public static io.airbyte.config.Geography toPersistenceGeography(final Geography apiGeography) { - return Enums.convertTo(apiGeography, io.airbyte.config.Geography.class); - } - - public static Schedule.TimeUnit toPersistenceTimeUnit(final ConnectionSchedule.TimeUnitEnum apiTimeUnit) { - return Enums.convertTo(apiTimeUnit, Schedule.TimeUnit.class); - } - - public static BasicSchedule.TimeUnit toBasicScheduleTimeUnit(final ConnectionSchedule.TimeUnitEnum apiTimeUnit) { - return Enums.convertTo(apiTimeUnit, BasicSchedule.TimeUnit.class); - } - - public static BasicSchedule.TimeUnit toBasicScheduleTimeUnit(final ConnectionScheduleDataBasicSchedule.TimeUnitEnum apiTimeUnit) { - return Enums.convertTo(apiTimeUnit, BasicSchedule.TimeUnit.class); - } - - public static Schedule.TimeUnit toLegacyScheduleTimeUnit(final ConnectionScheduleDataBasicSchedule.TimeUnitEnum timeUnit) { - return Enums.convertTo(timeUnit, Schedule.TimeUnit.class); - } - - public static ConnectionScheduleDataBasicSchedule.TimeUnitEnum toApiBasicScheduleTimeUnit(final BasicSchedule.TimeUnit timeUnit) { - return Enums.convertTo(timeUnit, ConnectionScheduleDataBasicSchedule.TimeUnitEnum.class); - } - - public static ConnectionScheduleDataBasicSchedule.TimeUnitEnum toApiBasicScheduleTimeUnit(final Schedule.TimeUnit timeUnit) { - return Enums.convertTo(timeUnit, ConnectionScheduleDataBasicSchedule.TimeUnitEnum.class); - } - - public static io.airbyte.api.model.generated.ConnectionScheduleType toApiConnectionScheduleType(final StandardSync standardSync) { - if (standardSync.getScheduleType() != null) { - switch (standardSync.getScheduleType()) { - case MANUAL -> { - return io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL; - } - case BASIC_SCHEDULE -> { - return io.airbyte.api.model.generated.ConnectionScheduleType.BASIC; - } - case CRON -> { - return io.airbyte.api.model.generated.ConnectionScheduleType.CRON; - } - default -> throw new RuntimeException("Unexpected scheduleType " + standardSync.getScheduleType()); - } - } else if (standardSync.getManual()) { - // Legacy schema, manual sync. - return io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL; - } else { - // Legacy schema, basic schedule. - return io.airbyte.api.model.generated.ConnectionScheduleType.BASIC; - } - } - - public static io.airbyte.api.model.generated.ConnectionScheduleData toApiConnectionScheduleData(final StandardSync standardSync) { - if (standardSync.getScheduleType() != null) { - switch (standardSync.getScheduleType()) { - case MANUAL -> { - return null; - } - case BASIC_SCHEDULE -> { - return new ConnectionScheduleData() - .basicSchedule(new ConnectionScheduleDataBasicSchedule() - .timeUnit(toApiBasicScheduleTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) - .units(standardSync.getScheduleData().getBasicSchedule().getUnits())); - } - case CRON -> { - return new ConnectionScheduleData() - .cron(new ConnectionScheduleDataCron() - .cronExpression(standardSync.getScheduleData().getCron().getCronExpression()) - .cronTimeZone(standardSync.getScheduleData().getCron().getCronTimeZone())); - } - default -> throw new RuntimeException("Unexpected scheduleType " + standardSync.getScheduleType()); - } - } else if (standardSync.getManual()) { - // Legacy schema, manual sync. - return null; - } else { - // Legacy schema, basic schedule. - return new ConnectionScheduleData() - .basicSchedule(new ConnectionScheduleDataBasicSchedule() - .timeUnit(toApiBasicScheduleTimeUnit(standardSync.getSchedule().getTimeUnit())) - .units(standardSync.getSchedule().getUnits())); - } - } - - public static ConnectionSchedule toLegacyConnectionSchedule(final StandardSync standardSync) { - if (standardSync.getScheduleType() != null) { - // Populate everything based on the new schema. - switch (standardSync.getScheduleType()) { - case MANUAL, CRON -> { - // We don't populate any legacy data here. - return null; - } - case BASIC_SCHEDULE -> { - return new ConnectionSchedule() - .timeUnit(toApiTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) - .units(standardSync.getScheduleData().getBasicSchedule().getUnits()); - } - default -> throw new RuntimeException("Unexpected scheduleType " + standardSync.getScheduleType()); - } - } else if (standardSync.getManual()) { - // Legacy schema, manual sync. - return null; - } else { - // Legacy schema, basic schedule. - return new ConnectionSchedule() - .timeUnit(toApiTimeUnit(standardSync.getSchedule().getTimeUnit())) - .units(standardSync.getSchedule().getUnits()); - } - } - - public static void populateConnectionReadSchedule(final StandardSync standardSync, final ConnectionRead connectionRead) { - connectionRead.scheduleType(toApiConnectionScheduleType(standardSync)); - connectionRead.scheduleData(toApiConnectionScheduleData(standardSync)); - - // TODO(https://github.com/airbytehq/airbyte/issues/11432): only return new schema once frontend is - // ready. - connectionRead.schedule(toLegacyConnectionSchedule(standardSync)); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/CatalogDiffConverters.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/CatalogDiffConverters.java deleted file mode 100644 index 77d763b0f5550..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/CatalogDiffConverters.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import io.airbyte.api.model.generated.FieldAdd; -import io.airbyte.api.model.generated.FieldRemove; -import io.airbyte.api.model.generated.FieldSchemaUpdate; -import io.airbyte.api.model.generated.FieldTransform; -import io.airbyte.api.model.generated.StreamTransform; -import io.airbyte.commons.enums.Enums; -import io.airbyte.protocol.models.transform_models.FieldTransformType; -import io.airbyte.protocol.models.transform_models.StreamTransformType; -import io.airbyte.workers.helper.ProtocolConverters; -import java.util.List; -import java.util.Optional; - -/** - * Utility methods for converting between internal and API representation of catalog diffs. - */ -public class CatalogDiffConverters { - - public static StreamTransform streamTransformToApi(final io.airbyte.protocol.models.transform_models.StreamTransform transform) { - return new StreamTransform() - .transformType(Enums.convertTo(transform.getTransformType(), StreamTransform.TransformTypeEnum.class)) - .streamDescriptor(ProtocolConverters.streamDescriptorToApi(transform.getStreamDescriptor())) - .updateStream(updateStreamToApi(transform).orElse(null)); - } - - public static Optional> updateStreamToApi(final io.airbyte.protocol.models.transform_models.StreamTransform transform) { - if (transform.getTransformType() == StreamTransformType.UPDATE_STREAM) { - return Optional.ofNullable(transform.getUpdateStreamTransform() - .getFieldTransforms() - .stream() - .map(CatalogDiffConverters::fieldTransformToApi) - .toList()); - } else { - return Optional.empty(); - } - } - - public static FieldTransform fieldTransformToApi(final io.airbyte.protocol.models.transform_models.FieldTransform transform) { - return new FieldTransform() - .transformType(Enums.convertTo(transform.getTransformType(), FieldTransform.TransformTypeEnum.class)) - .fieldName(transform.getFieldName()) - .breaking(transform.breaking()) - .addField(addFieldToApi(transform).orElse(null)) - .removeField(removeFieldToApi(transform).orElse(null)) - .updateFieldSchema(updateFieldToApi(transform).orElse(null)); - } - - private static Optional addFieldToApi(final io.airbyte.protocol.models.transform_models.FieldTransform transform) { - if (transform.getTransformType() == FieldTransformType.ADD_FIELD) { - return Optional.of(new FieldAdd() - .schema(transform.getAddFieldTransform().getSchema())); - } else { - return Optional.empty(); - } - } - - private static Optional removeFieldToApi(final io.airbyte.protocol.models.transform_models.FieldTransform transform) { - if (transform.getTransformType() == FieldTransformType.REMOVE_FIELD) { - return Optional.of(new FieldRemove() - .schema(transform.getRemoveFieldTransform().getSchema())); - } else { - return Optional.empty(); - } - } - - private static Optional updateFieldToApi(final io.airbyte.protocol.models.transform_models.FieldTransform transform) { - if (transform.getTransformType() == FieldTransformType.UPDATE_FIELD_SCHEMA) { - return Optional.of(new FieldSchemaUpdate() - .oldSchema(transform.getUpdateFieldTransform().getOldSchema()) - .newSchema(transform.getUpdateFieldTransform().getNewSchema())); - } else { - return Optional.empty(); - } - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ConfigurationUpdate.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ConfigurationUpdate.java deleted file mode 100644 index b4cab910c03cd..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/ConfigurationUpdate.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.UUID; - -@Singleton -public class ConfigurationUpdate { - - private final ConfigRepository configRepository; - private final SecretsRepositoryReader secretsRepositoryReader; - private final JsonSecretsProcessor secretsProcessor; - - public ConfigurationUpdate(final ConfigRepository configRepository, final SecretsRepositoryReader secretsRepositoryReader) { - this(configRepository, secretsRepositoryReader, JsonSecretsProcessor.builder() - .copySecrets(true) - .build()); - } - - public ConfigurationUpdate(final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final JsonSecretsProcessor secretsProcessor) { - this.configRepository = configRepository; - this.secretsRepositoryReader = secretsRepositoryReader; - this.secretsProcessor = secretsProcessor; - } - - public SourceConnection source(final UUID sourceId, final String sourceName, final JsonNode newConfiguration) - throws ConfigNotFoundException, IOException, JsonValidationException { - // get existing source - final SourceConnection persistedSource = secretsRepositoryReader.getSourceConnectionWithSecrets(sourceId); - persistedSource.setName(sourceName); - // get spec - final StandardSourceDefinition sourceDefinition = configRepository.getStandardSourceDefinition(persistedSource.getSourceDefinitionId()); - final ConnectorSpecification spec = sourceDefinition.getSpec(); - // copy any necessary secrets from the current source to the incoming updated source - final JsonNode updatedConfiguration = secretsProcessor.copySecrets( - persistedSource.getConfiguration(), - newConfiguration, - spec.getConnectionSpecification()); - - return Jsons.clone(persistedSource).withConfiguration(updatedConfiguration); - } - - public DestinationConnection destination(final UUID destinationId, final String destName, final JsonNode newConfiguration) - throws ConfigNotFoundException, IOException, JsonValidationException { - // get existing destination - final DestinationConnection persistedDestination = secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationId); - persistedDestination.setName(destName); - // get spec - final StandardDestinationDefinition destinationDefinition = configRepository - .getStandardDestinationDefinition(persistedDestination.getDestinationDefinitionId()); - final ConnectorSpecification spec = destinationDefinition.getSpec(); - // copy any necessary secrets from the current destination to the incoming updated destination - final JsonNode updatedConfiguration = secretsProcessor.copySecrets( - persistedDestination.getConfiguration(), - newConfiguration, - spec.getConnectionSpecification()); - - return Jsons.clone(persistedDestination).withConfiguration(updatedConfiguration); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/JobConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/JobConverter.java deleted file mode 100644 index 1a5e59f7d1a63..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/JobConverter.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import io.airbyte.api.model.generated.AttemptFailureOrigin; -import io.airbyte.api.model.generated.AttemptFailureReason; -import io.airbyte.api.model.generated.AttemptFailureSummary; -import io.airbyte.api.model.generated.AttemptFailureType; -import io.airbyte.api.model.generated.AttemptInfoRead; -import io.airbyte.api.model.generated.AttemptNormalizationStatusRead; -import io.airbyte.api.model.generated.AttemptRead; -import io.airbyte.api.model.generated.AttemptStats; -import io.airbyte.api.model.generated.AttemptStatus; -import io.airbyte.api.model.generated.AttemptStreamStats; -import io.airbyte.api.model.generated.DestinationDefinitionRead; -import io.airbyte.api.model.generated.JobConfigType; -import io.airbyte.api.model.generated.JobDebugRead; -import io.airbyte.api.model.generated.JobInfoLightRead; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.JobOptionalRead; -import io.airbyte.api.model.generated.JobRead; -import io.airbyte.api.model.generated.JobStatus; -import io.airbyte.api.model.generated.JobWithAttemptsRead; -import io.airbyte.api.model.generated.LogRead; -import io.airbyte.api.model.generated.ResetConfig; -import io.airbyte.api.model.generated.SourceDefinitionRead; -import io.airbyte.api.model.generated.SynchronousJobRead; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.scheduler.SynchronousJobMetadata; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.JobOutput; -import io.airbyte.config.ResetSourceConfiguration; -import io.airbyte.config.StandardSyncOutput; -import io.airbyte.config.StandardSyncSummary; -import io.airbyte.config.StreamSyncStats; -import io.airbyte.config.SyncStats; -import io.airbyte.config.helpers.LogClientSingleton; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.persistence.job.models.Attempt; -import io.airbyte.persistence.job.models.AttemptNormalizationStatus; -import io.airbyte.persistence.job.models.Job; -import io.airbyte.workers.helper.ProtocolConverters; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.nio.file.Path; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -@Singleton -public class JobConverter { - - private final WorkerEnvironment workerEnvironment; - private final LogConfigs logConfigs; - - public JobConverter(final WorkerEnvironment workerEnvironment, final LogConfigs logConfigs) { - this.workerEnvironment = workerEnvironment; - this.logConfigs = logConfigs; - } - - public JobInfoRead getJobInfoRead(final Job job) { - return new JobInfoRead() - .job(getJobWithAttemptsRead(job).getJob()) - .attempts(job.getAttempts().stream().map(this::getAttemptInfoRead).collect(Collectors.toList())); - } - - public JobInfoLightRead getJobInfoLightRead(final Job job) { - return new JobInfoLightRead().job(getJobRead(job)); - } - - public JobOptionalRead getJobOptionalRead(final Job job) { - return new JobOptionalRead().job(getJobRead(job)); - } - - public static JobDebugRead getDebugJobInfoRead(final JobInfoRead jobInfoRead, - final SourceDefinitionRead sourceDefinitionRead, - final DestinationDefinitionRead destinationDefinitionRead, - final AirbyteVersion airbyteVersion) { - return new JobDebugRead() - .id(jobInfoRead.getJob().getId()) - .configId(jobInfoRead.getJob().getConfigId()) - .configType(jobInfoRead.getJob().getConfigType()) - .status(jobInfoRead.getJob().getStatus()) - .airbyteVersion(airbyteVersion.serialize()) - .sourceDefinition(sourceDefinitionRead) - .destinationDefinition(destinationDefinitionRead); - } - - public static JobWithAttemptsRead getJobWithAttemptsRead(final Job job) { - return new JobWithAttemptsRead() - .job(getJobRead(job)) - .attempts(job.getAttempts().stream().map(JobConverter::getAttemptRead).toList()); - } - - public static JobRead getJobRead(final Job job) { - final String configId = job.getScope(); - final JobConfigType configType = Enums.convertTo(job.getConfigType(), JobConfigType.class); - - return new JobRead() - .id(job.getId()) - .configId(configId) - .configType(configType) - .resetConfig(extractResetConfigIfReset(job).orElse(null)) - .createdAt(job.getCreatedAtInSecond()) - .updatedAt(job.getUpdatedAtInSecond()) - .startedAt(job.getStartedAtInSecond().isPresent() ? job.getStartedAtInSecond().get() : null) - .status(Enums.convertTo(job.getStatus(), JobStatus.class)); - } - - /** - * If the job is of type RESET, extracts the part of the reset config that we expose in the API. - * Otherwise, returns empty optional. - * - * @param job - job - * @return api representation of reset config - */ - private static Optional extractResetConfigIfReset(final Job job) { - if (job.getConfigType() == ConfigType.RESET_CONNECTION) { - final ResetSourceConfiguration resetSourceConfiguration = job.getConfig().getResetConnection().getResetSourceConfiguration(); - if (resetSourceConfiguration == null) { - return Optional.empty(); - } - return Optional.ofNullable( - new ResetConfig().streamsToReset(job.getConfig().getResetConnection().getResetSourceConfiguration().getStreamsToReset() - .stream() - .map(ProtocolConverters::streamDescriptorToApi) - .toList())); - } else { - return Optional.empty(); - } - } - - public AttemptInfoRead getAttemptInfoRead(final Attempt attempt) { - return new AttemptInfoRead() - .attempt(getAttemptRead(attempt)) - .logs(getLogRead(attempt.getLogPath())); - } - - public static AttemptRead getAttemptRead(final Attempt attempt) { - return new AttemptRead() - .id((long) attempt.getAttemptNumber()) - .status(Enums.convertTo(attempt.getStatus(), AttemptStatus.class)) - .bytesSynced(attempt.getOutput() // TODO (parker) remove after frontend switches to totalStats - .map(JobOutput::getSync) - .map(StandardSyncOutput::getStandardSyncSummary) - .map(StandardSyncSummary::getBytesSynced) - .orElse(null)) - .recordsSynced(attempt.getOutput() // TODO (parker) remove after frontend switches to totalStats - .map(JobOutput::getSync) - .map(StandardSyncOutput::getStandardSyncSummary) - .map(StandardSyncSummary::getRecordsSynced) - .orElse(null)) - .totalStats(getTotalAttemptStats(attempt)) - .streamStats(getAttemptStreamStats(attempt)) - .createdAt(attempt.getCreatedAtInSecond()) - .updatedAt(attempt.getUpdatedAtInSecond()) - .endedAt(attempt.getEndedAtInSecond().orElse(null)) - .failureSummary(getAttemptFailureSummary(attempt)); - } - - private static AttemptStats getTotalAttemptStats(final Attempt attempt) { - final SyncStats totalStats = attempt.getOutput() - .map(JobOutput::getSync) - .map(StandardSyncOutput::getStandardSyncSummary) - .map(StandardSyncSummary::getTotalStats) - .orElse(null); - - if (totalStats == null) { - return null; - } - - return new AttemptStats() - .bytesEmitted(totalStats.getBytesEmitted()) - .recordsEmitted(totalStats.getRecordsEmitted()) - .stateMessagesEmitted(totalStats.getSourceStateMessagesEmitted()) - .recordsCommitted(totalStats.getRecordsCommitted()); - } - - private static List getAttemptStreamStats(final Attempt attempt) { - final List streamStats = attempt.getOutput() - .map(JobOutput::getSync) - .map(StandardSyncOutput::getStandardSyncSummary) - .map(StandardSyncSummary::getStreamStats) - .orElse(null); - - if (streamStats == null) { - return null; - } - - return streamStats.stream() - .map(streamStat -> new AttemptStreamStats() - .streamName(streamStat.getStreamName()) - .stats(new AttemptStats() - .bytesEmitted(streamStat.getStats().getBytesEmitted()) - .recordsEmitted(streamStat.getStats().getRecordsEmitted()) - .stateMessagesEmitted(streamStat.getStats().getSourceStateMessagesEmitted()) - .recordsCommitted(streamStat.getStats().getRecordsCommitted()))) - .collect(Collectors.toList()); - } - - private static AttemptFailureSummary getAttemptFailureSummary(final Attempt attempt) { - final io.airbyte.config.AttemptFailureSummary failureSummary = attempt.getFailureSummary().orElse(null); - - if (failureSummary == null) { - return null; - } - - return new AttemptFailureSummary() - .failures(failureSummary.getFailures().stream().map(failure -> new AttemptFailureReason() - .failureOrigin(Enums.convertTo(failure.getFailureOrigin(), AttemptFailureOrigin.class)) - .failureType(Enums.convertTo(failure.getFailureType(), AttemptFailureType.class)) - .externalMessage(failure.getExternalMessage()) - .internalMessage(failure.getInternalMessage()) - .stacktrace(failure.getStacktrace()) - .timestamp(failure.getTimestamp()) - .retryable(failure.getRetryable())) - .collect(Collectors.toList())) - .partialSuccess(failureSummary.getPartialSuccess()); - } - - public LogRead getLogRead(final Path logPath) { - try { - return new LogRead().logLines(LogClientSingleton.getInstance().getJobLogFile(workerEnvironment, logConfigs, logPath)); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - - public SynchronousJobRead getSynchronousJobRead(final SynchronousResponse response) { - return getSynchronousJobRead(response.getMetadata()); - } - - public SynchronousJobRead getSynchronousJobRead(final SynchronousJobMetadata metadata) { - final JobConfigType configType = Enums.convertTo(metadata.getConfigType(), JobConfigType.class); - - return new SynchronousJobRead() - .id(metadata.getId()) - .configType(configType) - .configId(String.valueOf(metadata.getConfigId())) - .createdAt(metadata.getCreatedAt()) - .endedAt(metadata.getEndedAt()) - .succeeded(metadata.isSucceeded()) - .connectorConfigurationUpdated(metadata.isConnectorConfigurationUpdated()) - .logs(getLogRead(metadata.getLogPath())); - } - - public static AttemptNormalizationStatusRead convertAttemptNormalizationStatus( - final AttemptNormalizationStatus databaseStatus) { - return new AttemptNormalizationStatusRead() - .attemptNumber(databaseStatus.attemptNumber()) - .hasRecordsCommitted(!databaseStatus.recordsCommitted().isEmpty()) - .recordsCommitted(databaseStatus.recordsCommitted().orElse(0L)) - .hasNormalizationFailed(databaseStatus.normalizationFailed()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/NotificationConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/NotificationConverter.java deleted file mode 100644 index 9fb97c319d5c7..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/NotificationConverter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import io.airbyte.commons.enums.Enums; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -public class NotificationConverter { - - public static List toConfigList(final List notifications) { - if (notifications == null) { - return Collections.emptyList(); - } - return notifications.stream().map(NotificationConverter::toConfig).collect(Collectors.toList()); - } - - public static io.airbyte.config.Notification toConfig(final io.airbyte.api.model.generated.Notification notification) { - return new io.airbyte.config.Notification() - .withNotificationType(Enums.convertTo(notification.getNotificationType(), io.airbyte.config.Notification.NotificationType.class)) - .withSendOnSuccess(notification.getSendOnSuccess()) - .withSendOnFailure(notification.getSendOnFailure()) - .withSlackConfiguration(toConfig(notification.getSlackConfiguration())); - } - - private static io.airbyte.config.SlackNotificationConfiguration toConfig(final io.airbyte.api.model.generated.SlackNotificationConfiguration notification) { - return new io.airbyte.config.SlackNotificationConfiguration() - .withWebhook(notification.getWebhook()); - } - - public static List toApiList(final List notifications) { - return notifications.stream().map(NotificationConverter::toApi).collect(Collectors.toList()); - } - - public static io.airbyte.api.model.generated.Notification toApi(final io.airbyte.config.Notification notification) { - return new io.airbyte.api.model.generated.Notification() - .notificationType(Enums.convertTo(notification.getNotificationType(), io.airbyte.api.model.generated.NotificationType.class)) - .sendOnSuccess(notification.getSendOnSuccess()) - .sendOnFailure(notification.getSendOnFailure()) - .slackConfiguration(toApi(notification.getSlackConfiguration())); - } - - private static io.airbyte.api.model.generated.SlackNotificationConfiguration toApi(final io.airbyte.config.SlackNotificationConfiguration notification) { - return new io.airbyte.api.model.generated.SlackNotificationConfiguration() - .webhook(notification.getWebhook()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OauthModelConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OauthModelConverter.java deleted file mode 100644 index 4c43cdecab5c4..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OauthModelConverter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import io.airbyte.api.model.generated.AdvancedAuth; -import io.airbyte.api.model.generated.AdvancedAuth.AuthFlowTypeEnum; -import io.airbyte.api.model.generated.AuthSpecification; -import io.airbyte.api.model.generated.OAuth2Specification; -import io.airbyte.api.model.generated.OAuthConfigSpecification; -import io.airbyte.protocol.models.ConnectorSpecification; -import java.util.List; -import java.util.Optional; - -public class OauthModelConverter { - - public static Optional getAuthSpec(final ConnectorSpecification spec) { - if (spec.getAuthSpecification() == null) { - return Optional.empty(); - } - final io.airbyte.protocol.models.AuthSpecification incomingAuthSpec = spec.getAuthSpecification(); - - final AuthSpecification authSpecification = new AuthSpecification(); - if (incomingAuthSpec.getAuthType() == io.airbyte.protocol.models.AuthSpecification.AuthType.OAUTH_2_0) { - authSpecification.authType(AuthSpecification.AuthTypeEnum.OAUTH2_0) - .oauth2Specification(new OAuth2Specification() - .rootObject(incomingAuthSpec.getOauth2Specification().getRootObject()) - .oauthFlowInitParameters(incomingAuthSpec.getOauth2Specification().getOauthFlowInitParameters()) - .oauthFlowOutputParameters(incomingAuthSpec.getOauth2Specification().getOauthFlowOutputParameters())); - } - return Optional.of(authSpecification); - } - - public static Optional getAdvancedAuth(final ConnectorSpecification spec) { - if (spec.getAdvancedAuth() == null) { - return Optional.empty(); - } - final io.airbyte.protocol.models.AdvancedAuth incomingAdvancedAuth = spec.getAdvancedAuth(); - final AdvancedAuth advancedAuth = new AdvancedAuth(); - if (List.of(io.airbyte.protocol.models.AdvancedAuth.AuthFlowType.OAUTH_1_0, io.airbyte.protocol.models.AdvancedAuth.AuthFlowType.OAUTH_2_0) - .contains(incomingAdvancedAuth.getAuthFlowType())) { - final AuthFlowTypeEnum oauthFlowType; - if (io.airbyte.protocol.models.AdvancedAuth.AuthFlowType.OAUTH_1_0.equals(incomingAdvancedAuth.getAuthFlowType())) { - oauthFlowType = AuthFlowTypeEnum.OAUTH1_0; - } else { - oauthFlowType = AuthFlowTypeEnum.OAUTH2_0; - } - final io.airbyte.protocol.models.OAuthConfigSpecification incomingOAuthConfigSpecification = incomingAdvancedAuth.getOauthConfigSpecification(); - advancedAuth - .authFlowType(oauthFlowType) - .predicateKey(incomingAdvancedAuth.getPredicateKey()) - .predicateValue(incomingAdvancedAuth.getPredicateValue()) - .oauthConfigSpecification(new OAuthConfigSpecification() - .oauthUserInputFromConnectorConfigSpecification(incomingOAuthConfigSpecification.getOauthUserInputFromConnectorConfigSpecification()) - .completeOAuthOutputSpecification(incomingOAuthConfigSpecification.getCompleteOauthOutputSpecification()) - .completeOAuthServerInputSpecification(incomingOAuthConfigSpecification.getCompleteOauthServerInputSpecification()) - .completeOAuthServerOutputSpecification(incomingOAuthConfigSpecification.getCompleteOauthServerOutputSpecification())); - } - return Optional.of(advancedAuth); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OperationsConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OperationsConverter.java deleted file mode 100644 index 6b2d2167d91d2..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/OperationsConverter.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import static io.airbyte.api.model.generated.OperatorWebhook.WebhookTypeEnum.DBTCLOUD; - -import com.google.common.base.Preconditions; -import io.airbyte.api.model.generated.OperationRead; -import io.airbyte.api.model.generated.OperatorConfiguration; -import io.airbyte.api.model.generated.OperatorNormalization.OptionEnum; -import io.airbyte.api.model.generated.OperatorWebhookDbtCloud; -import io.airbyte.commons.enums.Enums; -import io.airbyte.config.OperatorDbt; -import io.airbyte.config.OperatorNormalization; -import io.airbyte.config.OperatorNormalization.Option; -import io.airbyte.config.OperatorWebhook; -import io.airbyte.config.StandardSyncOperation; -import io.airbyte.config.StandardSyncOperation.OperatorType; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class OperationsConverter { - - public static void populateOperatorConfigFromApi(final OperatorConfiguration operatorConfig, final StandardSyncOperation standardSyncOperation) { - standardSyncOperation.withOperatorType(Enums.convertTo(operatorConfig.getOperatorType(), OperatorType.class)); - switch (operatorConfig.getOperatorType()) { - case NORMALIZATION -> { - Preconditions.checkArgument(operatorConfig.getNormalization() != null); - standardSyncOperation.withOperatorNormalization(new OperatorNormalization() - .withOption(Enums.convertTo(operatorConfig.getNormalization().getOption(), Option.class))); - // Null out the other configs, since it's mutually exclusive. We need to do this if it's an update. - standardSyncOperation.withOperatorDbt(null); - standardSyncOperation.withOperatorWebhook(null); - } - case DBT -> { - Preconditions.checkArgument(operatorConfig.getDbt() != null); - standardSyncOperation.withOperatorDbt(new OperatorDbt() - .withGitRepoUrl(operatorConfig.getDbt().getGitRepoUrl()) - .withGitRepoBranch(operatorConfig.getDbt().getGitRepoBranch()) - .withDockerImage(operatorConfig.getDbt().getDockerImage()) - .withDbtArguments(operatorConfig.getDbt().getDbtArguments())); - // Null out the other configs, since they're mutually exclusive. We need to do this if it's an - // update. - standardSyncOperation.withOperatorNormalization(null); - standardSyncOperation.withOperatorWebhook(null); - } - case WEBHOOK -> { - Preconditions.checkArgument(operatorConfig.getWebhook() != null); - // TODO(mfsiega-airbyte): check that the webhook config id references a real webhook config. - standardSyncOperation.withOperatorWebhook(webhookOperatorFromConfig(operatorConfig.getWebhook())); - // Null out the other configs, since it's mutually exclusive. We need to do this if it's an update. - standardSyncOperation.withOperatorNormalization(null); - standardSyncOperation.withOperatorDbt(null); - } - } - } - - public static OperationRead operationReadFromPersistedOperation(final StandardSyncOperation standardSyncOperation) { - final OperatorConfiguration operatorConfiguration = new OperatorConfiguration() - .operatorType(Enums.convertTo(standardSyncOperation.getOperatorType(), io.airbyte.api.model.generated.OperatorType.class)); - if (standardSyncOperation.getOperatorType() == null) { - // TODO(mfsiega-airbyte): this case shouldn't happen, but the API today would tolerate it. After - // verifying that it really can't happen, turn this into a precondition. - return new OperationRead() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .operationId(standardSyncOperation.getOperationId()) - .name(standardSyncOperation.getName()); - } - switch (standardSyncOperation.getOperatorType()) { - case NORMALIZATION -> { - Preconditions.checkArgument(standardSyncOperation.getOperatorNormalization() != null); - operatorConfiguration.normalization(new io.airbyte.api.model.generated.OperatorNormalization() - .option(Enums.convertTo(standardSyncOperation.getOperatorNormalization().getOption(), OptionEnum.class))); - } - case DBT -> { - Preconditions.checkArgument(standardSyncOperation.getOperatorDbt() != null); - operatorConfiguration.dbt(new io.airbyte.api.model.generated.OperatorDbt() - .gitRepoUrl(standardSyncOperation.getOperatorDbt().getGitRepoUrl()) - .gitRepoBranch(standardSyncOperation.getOperatorDbt().getGitRepoBranch()) - .dockerImage(standardSyncOperation.getOperatorDbt().getDockerImage()) - .dbtArguments(standardSyncOperation.getOperatorDbt().getDbtArguments())); - } - case WEBHOOK -> { - Preconditions.checkArgument(standardSyncOperation.getOperatorWebhook() != null); - operatorConfiguration.webhook(webhookOperatorFromPersistence(standardSyncOperation.getOperatorWebhook())); - } - } - return new OperationRead() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .operationId(standardSyncOperation.getOperationId()) - .name(standardSyncOperation.getName()) - .operatorConfiguration(operatorConfiguration); - } - - private static OperatorWebhook webhookOperatorFromConfig(io.airbyte.api.model.generated.OperatorWebhook webhookConfig) { - final var operatorWebhook = new OperatorWebhook().withWebhookConfigId(webhookConfig.getWebhookConfigId()); - // TODO(mfsiega-airbyte): remove this once the frontend is sending the new format. - if (webhookConfig.getWebhookType() == null) { - return operatorWebhook - .withExecutionUrl(webhookConfig.getExecutionUrl()) - .withExecutionBody(webhookConfig.getExecutionBody()); - } - switch (webhookConfig.getWebhookType()) { - case DBTCLOUD -> { - return operatorWebhook - .withExecutionUrl(DbtCloudOperationConverter.getExecutionUrlFrom(webhookConfig.getDbtCloud())) - .withExecutionBody(DbtCloudOperationConverter.getDbtCloudExecutionBody()); - } - // Future webhook operator types added here. - } - throw new IllegalArgumentException("Unsupported webhook operation type"); - } - - private static io.airbyte.api.model.generated.OperatorWebhook webhookOperatorFromPersistence(final OperatorWebhook persistedWebhook) { - final io.airbyte.api.model.generated.OperatorWebhook webhookOperator = new io.airbyte.api.model.generated.OperatorWebhook() - .webhookConfigId(persistedWebhook.getWebhookConfigId()); - OperatorWebhookDbtCloud dbtCloudOperator = DbtCloudOperationConverter.parseFrom(persistedWebhook); - if (dbtCloudOperator != null) { - webhookOperator.webhookType(DBTCLOUD).dbtCloud(dbtCloudOperator); - // TODO(mfsiega-airbyte): remove once frontend switches to new format. - // Dual-write deprecated webhook format. - webhookOperator.executionUrl(DbtCloudOperationConverter.getExecutionUrlFrom(dbtCloudOperator)); - webhookOperator.executionBody(DbtCloudOperationConverter.getDbtCloudExecutionBody()); - } else { - throw new IllegalArgumentException("Unexpected webhook operator config"); - } - return webhookOperator; - } - - private static class DbtCloudOperationConverter { - - // See https://docs.getdbt.com/dbt-cloud/api-v2 for documentation on dbt Cloud API endpoints. - final static Pattern dbtUrlPattern = Pattern.compile("^https://cloud\\.getdbt\\.com/api/v2/accounts/(\\d+)/jobs/(\\d+)/run/$"); - private static final int ACCOUNT_REGEX_GROUP = 1; - private static final int JOB_REGEX_GROUP = 2; - - private static OperatorWebhookDbtCloud parseFrom(OperatorWebhook persistedWebhook) { - Matcher dbtCloudUrlMatcher = dbtUrlPattern.matcher(persistedWebhook.getExecutionUrl()); - final var dbtCloudConfig = new OperatorWebhookDbtCloud(); - if (dbtCloudUrlMatcher.matches()) { - dbtCloudConfig.setAccountId(Integer.valueOf(dbtCloudUrlMatcher.group(ACCOUNT_REGEX_GROUP))); - dbtCloudConfig.setJobId(Integer.valueOf(dbtCloudUrlMatcher.group(JOB_REGEX_GROUP))); - return dbtCloudConfig; - } - return null; - } - - private static String getExecutionUrlFrom(final OperatorWebhookDbtCloud dbtCloudConfig) { - return String.format("https://cloud.getdbt.com/api/v2/accounts/%d/jobs/%d/run/", dbtCloudConfig.getAccountId(), - dbtCloudConfig.getJobId()); - } - - private static String getDbtCloudExecutionBody() { - return "{\"cause\": \"airbyte\"}"; - } - - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/SpecFetcher.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/SpecFetcher.java deleted file mode 100644 index 0202b23a86b17..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/SpecFetcher.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import com.google.common.base.Preconditions; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.protocol.models.ConnectorSpecification; - -public class SpecFetcher { - - public static ConnectorSpecification getSpecFromJob(final SynchronousResponse response) { - Preconditions.checkState(response.isSuccess(), "Get Spec job failed."); - Preconditions.checkNotNull(response.getOutput(), "Get Spec job return null spec"); - - return response.getOutput(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkflowStateConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkflowStateConverter.java deleted file mode 100644 index af912a94dbd40..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkflowStateConverter.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import io.airbyte.api.model.generated.WorkflowStateRead; -import io.airbyte.commons.temporal.scheduling.state.WorkflowState; -import jakarta.inject.Singleton; - -@Singleton -public class WorkflowStateConverter { - - public WorkflowStateRead getWorkflowStateRead(final WorkflowState workflowState) { - return new WorkflowStateRead().running(workflowState.isRunning()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkspaceWebhookConfigsConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkspaceWebhookConfigsConverter.java deleted file mode 100644 index 9e9669ee299d2..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/converters/WorkspaceWebhookConfigsConverter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.api.model.generated.WebhookConfigRead; -import io.airbyte.api.model.generated.WebhookConfigWrite; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.WebhookConfig; -import io.airbyte.config.WebhookOperationConfigs; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -// NOTE: we suppress this warning because PMD thinks it can be a foreach loop in toApiReads but the -// compiler disagrees. -@SuppressWarnings("PMD.ForLoopCanBeForeach") -public class WorkspaceWebhookConfigsConverter { - - public static JsonNode toPersistenceWrite(List apiWebhookConfigs, Supplier uuidSupplier) { - if (apiWebhookConfigs == null) { - return Jsons.emptyObject(); - } - - final WebhookOperationConfigs configs = new WebhookOperationConfigs() - .withWebhookConfigs(apiWebhookConfigs.stream().map((item) -> toPersistenceConfig(uuidSupplier, item)).collect(Collectors.toList())); - - return Jsons.jsonNode(configs); - } - - /** - * Extract the read-only properties from a set of persisted webhook operation configs. - *

- * Specifically, returns the id and name but excludes the secret auth token. Note that we "manually" - * deserialize the JSON tree instead of deserializing to our internal schema -- - * WebhookOperationConfigs -- because the persisted JSON doesn't conform to that schema until we - * hydrate the secrets. Since we don't want to unnecessarily hydrate the secrets to read from the - * API, we do this instead. - *

- * TODO(mfsiega-airbyte): try find a cleaner way to handle this situation. - * - * @param persistedWebhookConfig - The JsonNode of the persisted webhook configs - * @return a list of (webhook id, name) pairs - */ - public static List toApiReads(final JsonNode persistedWebhookConfig) { - if (persistedWebhookConfig == null) { - return Collections.emptyList(); - } - - // NOTE: we deserialize it "by hand" because the secrets aren't hydrated, so we can't deserialize it - // into the usual shape. - // TODO(mfsiega-airbyte): find a cleaner way to handle this situation. - List configReads = new ArrayList<>(); - - final JsonNode configArray = persistedWebhookConfig.findPath("webhookConfigs"); - Iterator it = configArray.elements(); - while (it.hasNext()) { - JsonNode webhookConfig = it.next(); - configReads.add(toApiRead(webhookConfig)); - } - return configReads; - } - - private static WebhookConfig toPersistenceConfig(final Supplier uuidSupplier, final WebhookConfigWrite input) { - return new WebhookConfig() - .withId(uuidSupplier.get()) - .withName(input.getName()) - .withAuthToken(input.getAuthToken()); - } - - private static WebhookConfigRead toApiRead(final JsonNode configJson) { - final var read = new WebhookConfigRead(); - read.setId(UUID.fromString(configJson.findValue("id").asText())); - read.setName(configJson.findValue("name").asText()); - return read; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ApplicationErrorKnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ApplicationErrorKnownException.java deleted file mode 100644 index d7f73e42931e3..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ApplicationErrorKnownException.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -public class ApplicationErrorKnownException extends KnownException { - - public ApplicationErrorKnownException(final String message) { - super(message); - } - - public ApplicationErrorKnownException(final String message, final Throwable cause) { - super(message, cause); - } - - @Override - public int getHttpCode() { - return 422; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/BadObjectSchemaKnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/BadObjectSchemaKnownException.java deleted file mode 100644 index 426d3f0aa73a0..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/BadObjectSchemaKnownException.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -public class BadObjectSchemaKnownException extends KnownException { - - public BadObjectSchemaKnownException(final String message) { - super(message); - } - - public BadObjectSchemaKnownException(final String message, final Throwable cause) { - super(message, cause); - } - - @Override - public int getHttpCode() { - return 422; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ConnectFailureKnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ConnectFailureKnownException.java deleted file mode 100644 index a94d4b41ead97..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ConnectFailureKnownException.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -public class ConnectFailureKnownException extends KnownException { - - public ConnectFailureKnownException(final String message) { - super(message); - } - - public ConnectFailureKnownException(final String message, final Throwable cause) { - super(message, cause); - } - - @Override - public int getHttpCode() { - return 400; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundExceptionMapper.java deleted file mode 100644 index 1025be5710bc2..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundExceptionMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Produces -@Singleton -@Requires(classes = IdNotFoundKnownException.class) -public class IdNotFoundExceptionMapper implements ExceptionHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(IdNotFoundExceptionMapper.class); - - @Override - public HttpResponse handle(final HttpRequest request, final IdNotFoundKnownException exception) { - final IdNotFoundKnownException idnf = new IdNotFoundKnownException("Id not found: " + exception.getMessage(), exception); - LOGGER.error("Not found exception", idnf.getNotFoundKnownExceptionInfo()); - - return HttpResponse.status(HttpStatus.NOT_FOUND) - .body(KnownException.infoFromThrowableWithMessage(exception, "Internal Server Error: " + exception.getMessage())) - .contentType(MediaType.APPLICATION_JSON); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundKnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundKnownException.java deleted file mode 100644 index 14360386cbf37..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/IdNotFoundKnownException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.api.model.generated.NotFoundKnownExceptionInfo; -import org.apache.logging.log4j.core.util.Throwables; - -public class IdNotFoundKnownException extends KnownException { - - String id; - - public IdNotFoundKnownException(final String message, final String id) { - super(message); - this.id = id; - } - - public IdNotFoundKnownException(final String message, final String id, final Throwable cause) { - super(message, cause); - this.id = id; - } - - public IdNotFoundKnownException(final String message, final Throwable cause) { - super(message, cause); - } - - @Override - public int getHttpCode() { - return 404; - } - - public String getId() { - return id; - } - - public NotFoundKnownExceptionInfo getNotFoundKnownExceptionInfo() { - final NotFoundKnownExceptionInfo exceptionInfo = new NotFoundKnownExceptionInfo() - .exceptionClassName(this.getClass().getName()) - .message(this.getMessage()) - .exceptionStack(Throwables.toStringList(this)); - if (this.getCause() != null) { - exceptionInfo.rootCauseExceptionClassName(this.getClass().getClass().getName()); - exceptionInfo.rootCauseExceptionStack(Throwables.toStringList(this.getCause())); - } - exceptionInfo.id(this.getId()); - return exceptionInfo; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InternalServerKnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InternalServerKnownException.java deleted file mode 100644 index 6f328721af4af..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InternalServerKnownException.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -public class InternalServerKnownException extends KnownException { - - public InternalServerKnownException(final String message) { - super(message); - } - - public InternalServerKnownException(final String message, final Throwable cause) { - super(message, cause); - } - - @Override - public int getHttpCode() { - return 500; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidInputExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidInputExceptionMapper.java deleted file mode 100644 index 48306d05ab54b..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidInputExceptionMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.api.model.generated.InvalidInputExceptionInfo; -import io.airbyte.api.model.generated.InvalidInputProperty; -import io.airbyte.commons.json.Jsons; -import java.util.ArrayList; -import java.util.List; -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; -import org.apache.logging.log4j.core.util.Throwables; - -@Provider -public class InvalidInputExceptionMapper implements ExceptionMapper { - - public static InvalidInputExceptionInfo infoFromConstraints(final ConstraintViolationException cve) { - final InvalidInputExceptionInfo exceptionInfo = new InvalidInputExceptionInfo() - .exceptionClassName(cve.getClass().getName()) - .message("Some properties contained invalid input.") - .exceptionStack(Throwables.toStringList(cve)); - - final List props = new ArrayList(); - for (final ConstraintViolation cv : cve.getConstraintViolations()) { - props.add(new InvalidInputProperty() - .propertyPath(cv.getPropertyPath().toString()) - .message(cv.getMessage()) - .invalidValue(cv.getInvalidValue() != null ? cv.getInvalidValue().toString() : "null")); - } - exceptionInfo.validationErrors(props); - return exceptionInfo; - } - - @Override - public Response toResponse(final ConstraintViolationException e) { - return Response.status(Response.Status.BAD_REQUEST) - .entity(Jsons.serialize(InvalidInputExceptionMapper.infoFromConstraints(e))) - .type("application/json") - .build(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonExceptionMapper.java deleted file mode 100644 index 7cd7a297199f9..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonExceptionMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import com.fasterxml.jackson.core.JsonParseException; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -@Provider -public class InvalidJsonExceptionMapper implements ExceptionMapper { - - @Override - public Response toResponse(final JsonParseException e) { - return Response.status(422) - .entity(KnownException.infoFromThrowableWithMessage(e, "Invalid json. " + e.getMessage() + " " + e.getOriginalMessage())) - .type("application/json") - .build(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonInputExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonInputExceptionMapper.java deleted file mode 100644 index a0545fdf101f3..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/InvalidJsonInputExceptionMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import com.fasterxml.jackson.databind.JsonMappingException; -import io.airbyte.commons.json.Jsons; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -@Provider -public class InvalidJsonInputExceptionMapper implements ExceptionMapper { - - @Override - public Response toResponse(final JsonMappingException e) { - return Response.status(422) - .entity( - Jsons.serialize(KnownException.infoFromThrowableWithMessage(e, "Invalid json input. " + e.getMessage() + " " + e.getOriginalMessage()))) - .type("application/json") - .build(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownException.java deleted file mode 100644 index db35ccac7cd50..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.api.model.generated.KnownExceptionInfo; -import org.apache.logging.log4j.core.util.Throwables; - -public abstract class KnownException extends RuntimeException { - - public KnownException(final String message) { - super(message); - } - - public KnownException(final String message, final Throwable cause) { - super(message, cause); - } - - abstract public int getHttpCode(); - - public KnownExceptionInfo getKnownExceptionInfo() { - return KnownException.infoFromThrowable(this); - } - - public static KnownExceptionInfo infoFromThrowableWithMessage(final Throwable t, final String message) { - final KnownExceptionInfo exceptionInfo = new KnownExceptionInfo() - .exceptionClassName(t.getClass().getName()) - .message(message) - .exceptionStack(Throwables.toStringList(t)); - if (t.getCause() != null) { - exceptionInfo.rootCauseExceptionClassName(t.getClass().getClass().getName()); - exceptionInfo.rootCauseExceptionStack(Throwables.toStringList(t.getCause())); - } - return exceptionInfo; - } - - public static KnownExceptionInfo infoFromThrowable(final Throwable t) { - return infoFromThrowableWithMessage(t, t.getMessage()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownExceptionMapper.java deleted file mode 100644 index 6bbce96bca7f3..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/KnownExceptionMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.commons.json.Jsons; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Produces; -import jakarta.inject.Singleton; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Produces -@Singleton -@Requires(classes = KnownException.class) -public class KnownExceptionMapper implements ExceptionMapper { - - private static final Logger LOGGER = LoggerFactory.getLogger(KnownExceptionMapper.class); - - @Override - public Response toResponse(final KnownException e) { - LOGGER.info("Known exception", e.getKnownExceptionInfo()); - return Response.status(e.getHttpCode()) - .entity(Jsons.serialize(e.getKnownExceptionInfo())) - .type("application/json") - .build(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/NotFoundExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/NotFoundExceptionMapper.java deleted file mode 100644 index 152933ba9a434..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/NotFoundExceptionMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.commons.json.Jsons; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Provider -public class NotFoundExceptionMapper implements ExceptionMapper { - - private static final Logger LOGGER = LoggerFactory.getLogger(NotFoundExceptionMapper.class); - - @Override - public Response toResponse(final NotFoundException e) { - // Would like to send the id along but we don't have access to the http request anymore to fetch it - // from. TODO: Come back to this with issue #4189 - final IdNotFoundKnownException idnf = new IdNotFoundKnownException("Object not found. " + e.getMessage(), e); - LOGGER.error("Not found exception", idnf.getNotFoundKnownExceptionInfo()); - return Response.status(404) - .entity(Jsons.serialize(idnf.getNotFoundKnownExceptionInfo())) - .type("application/json") - .build(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UncaughtExceptionMapper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UncaughtExceptionMapper.java deleted file mode 100644 index ff738e6bae481..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UncaughtExceptionMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.api.model.generated.KnownExceptionInfo; -import io.airbyte.commons.json.Jsons; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Provider -public class UncaughtExceptionMapper implements ExceptionMapper { - - private static final Logger LOGGER = LoggerFactory.getLogger(UncaughtExceptionMapper.class); - - @Override - public Response toResponse(final Throwable e) { - LOGGER.error("Uncaught exception", e); - final KnownExceptionInfo exceptionInfo = KnownException.infoFromThrowableWithMessage(e, "Internal Server Error: " + e.getMessage()); - return Response.status(500) - .entity(Jsons.serialize(exceptionInfo)) - .type("application/json") - .build(); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UnsupportedProtocolVersionException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UnsupportedProtocolVersionException.java deleted file mode 100644 index 0d8a28921c838..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/UnsupportedProtocolVersionException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -import io.airbyte.commons.version.Version; - -public class UnsupportedProtocolVersionException extends KnownException { - - public UnsupportedProtocolVersionException(final Version current, final Version minSupported, final Version maxSupported) { - this(current.serialize(), minSupported, maxSupported); - } - - public UnsupportedProtocolVersionException(final String current, final Version minSupported, final Version maxSupported) { - super(String.format("Airbyte Protocol Version %s is not supported. (Must be within [%s:%s])", - current, minSupported.serialize(), maxSupported.serialize())); - } - - @Override - public int getHttpCode() { - return 400; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ValueConflictKnownException.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ValueConflictKnownException.java deleted file mode 100644 index d1ce98447c09e..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/errors/ValueConflictKnownException.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.errors; - -public class ValueConflictKnownException extends KnownException { - - public ValueConflictKnownException(final String message) { - super(message); - } - - public ValueConflictKnownException(final String message, final Throwable cause) { - super(message, cause); - } - - @Override - public int getHttpCode() { - return 409; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/AttemptHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/AttemptHandler.java deleted file mode 100644 index 5f3dd815a54da..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/AttemptHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.InternalOperationResult; -import io.airbyte.api.model.generated.SaveAttemptSyncConfigRequestBody; -import io.airbyte.api.model.generated.SaveStatsRequestBody; -import io.airbyte.api.model.generated.SetWorkflowInAttemptRequestBody; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.config.StreamSyncStats; -import io.airbyte.config.SyncStats; -import io.airbyte.persistence.job.JobPersistence; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class AttemptHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(AttemptHandler.class); - - private final JobPersistence jobPersistence; - - public AttemptHandler(final JobPersistence jobPersistence) { - this.jobPersistence = jobPersistence; - } - - public InternalOperationResult setWorkflowInAttempt(final SetWorkflowInAttemptRequestBody requestBody) { - try { - jobPersistence.setAttemptTemporalWorkflowInfo(requestBody.getJobId(), - requestBody.getAttemptNumber(), requestBody.getWorkflowId(), requestBody.getProcessingTaskQueue()); - } catch (final IOException ioe) { - LOGGER.error("IOException when setting temporal workflow in attempt;", ioe); - return new InternalOperationResult().succeeded(false); - } - return new InternalOperationResult().succeeded(true); - } - - public InternalOperationResult saveStats(final SaveStatsRequestBody requestBody) { - try { - final var stats = requestBody.getStats(); - final var streamStats = requestBody.getStreamStats().stream() - .map(s -> new StreamSyncStats() - .withStreamName(s.getStreamName()) - .withStreamNamespace(s.getStreamNamespace()) - .withStats(new SyncStats() - .withBytesEmitted(s.getStats().getBytesEmitted()) - .withRecordsEmitted(s.getStats().getRecordsEmitted()) - .withEstimatedBytes(s.getStats().getEstimatedBytes()) - .withEstimatedRecords(s.getStats().getEstimatedRecords()))) - .collect(Collectors.toList()); - - jobPersistence.writeStats(requestBody.getJobId(), requestBody.getAttemptNumber(), - stats.getEstimatedRecords(), stats.getEstimatedBytes(), stats.getRecordsEmitted(), stats.getBytesEmitted(), streamStats); - - } catch (final IOException ioe) { - LOGGER.error("IOException when setting temporal workflow in attempt;", ioe); - return new InternalOperationResult().succeeded(false); - } - - return new InternalOperationResult().succeeded(true); - } - - public InternalOperationResult saveSyncConfig(final SaveAttemptSyncConfigRequestBody requestBody) { - try { - jobPersistence.writeAttemptSyncConfig( - requestBody.getJobId(), - requestBody.getAttemptNumber(), - ApiPojoConverters.attemptSyncConfigToInternal(requestBody.getSyncConfig())); - } catch (final IOException ioe) { - LOGGER.error("IOException when saving AttemptSyncConfig for attempt;", ioe); - return new InternalOperationResult().succeeded(false); - } - return new InternalOperationResult().succeeded(true); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectionsHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectionsHandler.java deleted file mode 100644 index d159297329b9b..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/ConnectionsHandler.java +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; -import com.google.common.collect.Lists; -import io.airbyte.analytics.TrackingClient; -import io.airbyte.api.model.generated.AirbyteCatalog; -import io.airbyte.api.model.generated.AirbyteStreamConfiguration; -import io.airbyte.api.model.generated.CatalogDiff; -import io.airbyte.api.model.generated.ConnectionCreate; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; -import io.airbyte.api.model.generated.ConnectionSearch; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationSearch; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceSearch; -import io.airbyte.api.model.generated.StreamDescriptor; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.server.converters.CatalogDiffConverters; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.handlers.helpers.ConnectionMatcher; -import io.airbyte.commons.server.handlers.helpers.ConnectionScheduleHelper; -import io.airbyte.commons.server.handlers.helpers.DestinationMatcher; -import io.airbyte.commons.server.handlers.helpers.SourceMatcher; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.config.ActorCatalog; -import io.airbyte.config.BasicSchedule; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.FieldSelectionData; -import io.airbyte.config.Geography; -import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; -import io.airbyte.config.Schedule; -import io.airbyte.config.ScheduleData; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.ScheduleType; -import io.airbyte.config.StandardWorkspace; -import io.airbyte.config.helpers.ScheduleHelpers; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.WorkspaceHelper; -import io.airbyte.protocol.models.CatalogHelpers; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.validation.json.JsonValidationException; -import io.airbyte.workers.helper.ConnectionHelper; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class ConnectionsHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionsHandler.class); - - private final ConfigRepository configRepository; - private final Supplier uuidGenerator; - private final WorkspaceHelper workspaceHelper; - private final TrackingClient trackingClient; - private final EventRunner eventRunner; - private final ConnectionHelper connectionHelper; - - @VisibleForTesting - ConnectionsHandler(final ConfigRepository configRepository, - final Supplier uuidGenerator, - final WorkspaceHelper workspaceHelper, - final TrackingClient trackingClient, - final EventRunner eventRunner, - final ConnectionHelper connectionHelper) { - this.configRepository = configRepository; - this.uuidGenerator = uuidGenerator; - this.workspaceHelper = workspaceHelper; - this.trackingClient = trackingClient; - this.eventRunner = eventRunner; - this.connectionHelper = connectionHelper; - } - - @Deprecated(forRemoval = true) - public ConnectionsHandler(final ConfigRepository configRepository, - final WorkspaceHelper workspaceHelper, - final TrackingClient trackingClient, - final EventRunner eventRunner, - final ConnectionHelper connectionHelper) { - this(configRepository, - UUID::randomUUID, - workspaceHelper, - trackingClient, - eventRunner, - connectionHelper); - - } - - public ConnectionRead createConnection(final ConnectionCreate connectionCreate) - throws JsonValidationException, IOException, ConfigNotFoundException { - - // Validate source and destination - final SourceConnection sourceConnection = configRepository.getSourceConnection(connectionCreate.getSourceId()); - final DestinationConnection destinationConnection = configRepository.getDestinationConnection(connectionCreate.getDestinationId()); - - // Set this as default name if connectionCreate doesn't have it - final String defaultName = sourceConnection.getName() + " <> " + destinationConnection.getName(); - - final List operationIds = connectionCreate.getOperationIds() != null ? connectionCreate.getOperationIds() : Collections.emptyList(); - - ConnectionHelper.validateWorkspace(workspaceHelper, - connectionCreate.getSourceId(), - connectionCreate.getDestinationId(), - operationIds); - - final UUID connectionId = uuidGenerator.get(); - - // If not specified, default the NamespaceDefinition to 'source' - final NamespaceDefinitionType namespaceDefinitionType = - connectionCreate.getNamespaceDefinition() == null - ? NamespaceDefinitionType.SOURCE - : Enums.convertTo(connectionCreate.getNamespaceDefinition(), NamespaceDefinitionType.class); - - // persist sync - final StandardSync standardSync = new StandardSync() - .withConnectionId(connectionId) - .withName(connectionCreate.getName() != null ? connectionCreate.getName() : defaultName) - .withNamespaceDefinition(namespaceDefinitionType) - .withNamespaceFormat(connectionCreate.getNamespaceFormat()) - .withPrefix(connectionCreate.getPrefix()) - .withSourceId(connectionCreate.getSourceId()) - .withDestinationId(connectionCreate.getDestinationId()) - .withOperationIds(operationIds) - .withStatus(ApiPojoConverters.toPersistenceStatus(connectionCreate.getStatus())) - .withSourceCatalogId(connectionCreate.getSourceCatalogId()) - .withGeography(getGeographyFromConnectionCreateOrWorkspace(connectionCreate)) - .withBreakingChange(false) - .withNonBreakingChangesPreference( - ApiPojoConverters.toPersistenceNonBreakingChangesPreference(connectionCreate.getNonBreakingChangesPreference())); - if (connectionCreate.getResourceRequirements() != null) { - standardSync.withResourceRequirements(ApiPojoConverters.resourceRequirementsToInternal(connectionCreate.getResourceRequirements())); - } - - // TODO Undesirable behavior: sending a null configured catalog should not be valid? - if (connectionCreate.getSyncCatalog() != null) { - standardSync.withCatalog(CatalogConverter.toConfiguredProtocol(connectionCreate.getSyncCatalog())); - standardSync.withFieldSelectionData(CatalogConverter.getFieldSelectionData(connectionCreate.getSyncCatalog())); - } else { - standardSync.withCatalog(new ConfiguredAirbyteCatalog().withStreams(Collections.emptyList())); - standardSync.withFieldSelectionData(new FieldSelectionData()); - } - - if (connectionCreate.getSchedule() != null && connectionCreate.getScheduleType() != null) { - throw new JsonValidationException("supply old or new schedule schema but not both"); - } - - if (connectionCreate.getScheduleType() != null) { - ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(standardSync, connectionCreate.getScheduleType(), - connectionCreate.getScheduleData()); - } else { - populateSyncFromLegacySchedule(standardSync, connectionCreate); - } - - configRepository.writeStandardSync(standardSync); - - trackNewConnection(standardSync); - - try { - LOGGER.info("Starting a connection manager workflow"); - eventRunner.createConnectionManagerWorkflow(connectionId); - } catch (final Exception e) { - LOGGER.error("Start of the connection manager workflow failed", e); - configRepository.deleteStandardSync(standardSync.getConnectionId()); - throw e; - } - - return buildConnectionRead(connectionId); - } - - private Geography getGeographyFromConnectionCreateOrWorkspace(final ConnectionCreate connectionCreate) - throws JsonValidationException, ConfigNotFoundException, IOException { - - if (connectionCreate.getGeography() != null) { - return ApiPojoConverters.toPersistenceGeography(connectionCreate.getGeography()); - } - - // connectionCreate didn't specify a geography, so use the workspace default geography if one exists - final UUID workspaceId = workspaceHelper.getWorkspaceForSourceId(connectionCreate.getSourceId()); - final StandardWorkspace workspace = configRepository.getStandardWorkspaceNoSecrets(workspaceId, true); - - if (workspace.getDefaultGeography() != null) { - return workspace.getDefaultGeography(); - } - - // if the workspace doesn't have a default geography, default to 'auto' - return Geography.AUTO; - } - - private void populateSyncFromLegacySchedule(final StandardSync standardSync, final ConnectionCreate connectionCreate) { - if (connectionCreate.getSchedule() != null) { - final Schedule schedule = new Schedule() - .withTimeUnit(ApiPojoConverters.toPersistenceTimeUnit(connectionCreate.getSchedule().getTimeUnit())) - .withUnits(connectionCreate.getSchedule().getUnits()); - // Populate the legacy field. - // TODO(https://github.com/airbytehq/airbyte/issues/11432): remove. - standardSync - .withManual(false) - .withSchedule(schedule); - // Also write into the new field. This one will be consumed if populated. - standardSync - .withScheduleType(ScheduleType.BASIC_SCHEDULE); - standardSync.withScheduleData(new ScheduleData().withBasicSchedule( - new BasicSchedule().withTimeUnit(ApiPojoConverters.toBasicScheduleTimeUnit(connectionCreate.getSchedule().getTimeUnit())) - .withUnits(connectionCreate.getSchedule().getUnits()))); - } else { - standardSync.withManual(true); - standardSync.withScheduleType(ScheduleType.MANUAL); - } - } - - private void trackNewConnection(final StandardSync standardSync) { - try { - final UUID workspaceId = workspaceHelper.getWorkspaceForConnectionIdIgnoreExceptions(standardSync.getConnectionId()); - final Builder metadataBuilder = generateMetadata(standardSync); - trackingClient.track(workspaceId, "New Connection - Backend", metadataBuilder.build()); - } catch (final Exception e) { - LOGGER.error("failed while reporting usage.", e); - } - } - - private Builder generateMetadata(final StandardSync standardSync) { - final Builder metadata = ImmutableMap.builder(); - - final UUID connectionId = standardSync.getConnectionId(); - final StandardSourceDefinition sourceDefinition = configRepository - .getSourceDefinitionFromConnection(connectionId); - final StandardDestinationDefinition destinationDefinition = configRepository - .getDestinationDefinitionFromConnection(connectionId); - - metadata.put("connector_source", sourceDefinition.getName()); - metadata.put("connector_source_definition_id", sourceDefinition.getSourceDefinitionId()); - metadata.put("connector_destination", destinationDefinition.getName()); - metadata.put("connector_destination_definition_id", destinationDefinition.getDestinationDefinitionId()); - - final String frequencyString; - if (standardSync.getScheduleType() != null) { - frequencyString = getFrequencyStringFromScheduleType(standardSync.getScheduleType(), standardSync.getScheduleData()); - } else if (standardSync.getManual()) { - frequencyString = "manual"; - } else { - final long intervalInMinutes = TimeUnit.SECONDS.toMinutes(ScheduleHelpers.getIntervalInSecond(standardSync.getSchedule())); - frequencyString = intervalInMinutes + " min"; - } - metadata.put("frequency", frequencyString); - return metadata; - } - - public ConnectionRead updateConnection(final ConnectionUpdate connectionPatch) - throws ConfigNotFoundException, IOException, JsonValidationException { - - final UUID connectionId = connectionPatch.getConnectionId(); - - LOGGER.debug("Starting updateConnection for connectionId {}...", connectionId); - LOGGER.debug("incoming connectionPatch: {}", connectionPatch); - - final StandardSync sync = configRepository.getStandardSync(connectionId); - LOGGER.debug("initial StandardSync: {}", sync); - - validateConnectionPatch(workspaceHelper, sync, connectionPatch); - - final ConnectionRead initialConnectionRead = ApiPojoConverters.internalToConnectionRead(sync); - LOGGER.debug("initial ConnectionRead: {}", initialConnectionRead); - - applyPatchToStandardSync(sync, connectionPatch); - - LOGGER.debug("patched StandardSync before persisting: {}", sync); - configRepository.writeStandardSync(sync); - - eventRunner.update(connectionId); - - final ConnectionRead updatedRead = buildConnectionRead(connectionId); - LOGGER.debug("final connectionRead: {}", updatedRead); - - return updatedRead; - } - - /** - * Modifies the given StandardSync by applying changes from a partially-filled ConnectionUpdate - * patch. Any fields that are null in the patch will be left unchanged. - */ - private static void applyPatchToStandardSync(final StandardSync sync, final ConnectionUpdate patch) throws JsonValidationException { - // update the sync's schedule using the patch's scheduleType and scheduleData. validations occur in - // the helper to ensure both fields - // make sense together. - if (patch.getScheduleType() != null) { - ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(sync, patch.getScheduleType(), patch.getScheduleData()); - } - - // the rest of the fields are straightforward to patch. If present in the patch, set the field to - // the value - // in the patch. Otherwise, leave the field unchanged. - - if (patch.getSyncCatalog() != null) { - sync.setCatalog(CatalogConverter.toConfiguredProtocol(patch.getSyncCatalog())); - sync.withFieldSelectionData(CatalogConverter.getFieldSelectionData(patch.getSyncCatalog())); - } - - if (patch.getName() != null) { - sync.setName(patch.getName()); - } - - if (patch.getNamespaceDefinition() != null) { - sync.setNamespaceDefinition(Enums.convertTo(patch.getNamespaceDefinition(), NamespaceDefinitionType.class)); - } - - if (patch.getNamespaceFormat() != null) { - sync.setNamespaceFormat(patch.getNamespaceFormat()); - } - - if (patch.getPrefix() != null) { - sync.setPrefix(patch.getPrefix()); - } - - if (patch.getOperationIds() != null) { - sync.setOperationIds(patch.getOperationIds()); - } - - if (patch.getStatus() != null) { - sync.setStatus(ApiPojoConverters.toPersistenceStatus(patch.getStatus())); - } - - if (patch.getSourceCatalogId() != null) { - sync.setSourceCatalogId(patch.getSourceCatalogId()); - } - - if (patch.getResourceRequirements() != null) { - sync.setResourceRequirements(ApiPojoConverters.resourceRequirementsToInternal(patch.getResourceRequirements())); - } - - if (patch.getGeography() != null) { - sync.setGeography(ApiPojoConverters.toPersistenceGeography(patch.getGeography())); - } - - if (patch.getBreakingChange() != null) { - sync.setBreakingChange(patch.getBreakingChange()); - } - - if (patch.getNotifySchemaChanges() != null) { - sync.setNotifySchemaChanges(patch.getNotifySchemaChanges()); - } - - if (patch.getNonBreakingChangesPreference() != null) { - sync.setNonBreakingChangesPreference(ApiPojoConverters.toPersistenceNonBreakingChangesPreference(patch.getNonBreakingChangesPreference())); - } - } - - private void validateConnectionPatch(final WorkspaceHelper workspaceHelper, final StandardSync persistedSync, final ConnectionUpdate patch) { - // sanity check that we're updating the right connection - Preconditions.checkArgument(persistedSync.getConnectionId().equals(patch.getConnectionId())); - - // make sure all operationIds belong to the same workspace as the connection - ConnectionHelper.validateWorkspace( - workspaceHelper, persistedSync.getSourceId(), persistedSync.getDestinationId(), patch.getOperationIds()); - - // make sure the incoming schedule update is sensible. Note that schedule details are further - // validated in ConnectionScheduleHelper, this just - // sanity checks that fields are populated when they should be. - Preconditions.checkArgument( - patch.getSchedule() == null, - "ConnectionUpdate should only make changes to the schedule by setting scheduleType and scheduleData. 'schedule' is no longer supported."); - - if (patch.getScheduleType() == null) { - Preconditions.checkArgument( - patch.getScheduleData() == null, - "ConnectionUpdate should not include any scheduleData without also specifying a valid scheduleType."); - } else { - switch (patch.getScheduleType()) { - case MANUAL -> Preconditions.checkArgument( - patch.getScheduleData() == null, - "ConnectionUpdate should not include any scheduleData when setting the Connection scheduleType to MANUAL."); - case BASIC -> Preconditions.checkArgument( - patch.getScheduleData() != null, - "ConnectionUpdate should include scheduleData when setting the Connection scheduleType to BASIC."); - case CRON -> Preconditions.checkArgument( - patch.getScheduleData() != null, - "ConnectionUpdate should include scheduleData when setting the Connection scheduleType to CRON."); - - // shouldn't be possible to reach this case - default -> throw new RuntimeException("Unrecognized scheduleType!"); - } - } - } - - public ConnectionReadList listConnectionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - return listConnectionsForWorkspace(workspaceIdRequestBody, false); - } - - public ConnectionReadList listAllConnectionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - return listConnectionsForWorkspace(workspaceIdRequestBody, true); - } - - public ConnectionReadList listConnectionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody, final boolean includeDeleted) - throws JsonValidationException, IOException, ConfigNotFoundException { - final List connectionReads = Lists.newArrayList(); - - for (final StandardSync standardSync : configRepository.listWorkspaceStandardSyncs(workspaceIdRequestBody.getWorkspaceId(), includeDeleted)) { - connectionReads.add(ApiPojoConverters.internalToConnectionRead(standardSync)); - } - - return new ConnectionReadList().connections(connectionReads); - } - - public ConnectionReadList listConnectionsForSource(final UUID sourceId, final boolean includeDeleted) throws IOException { - final List connectionReads = Lists.newArrayList(); - for (final StandardSync standardSync : configRepository.listConnectionsBySource(sourceId, includeDeleted)) { - connectionReads.add(ApiPojoConverters.internalToConnectionRead(standardSync)); - } - return new ConnectionReadList().connections(connectionReads); - } - - public ConnectionReadList listConnections() throws JsonValidationException, ConfigNotFoundException, IOException { - final List connectionReads = Lists.newArrayList(); - - for (final StandardSync standardSync : configRepository.listStandardSyncs()) { - if (standardSync.getStatus() == StandardSync.Status.DEPRECATED) { - continue; - } - connectionReads.add(ApiPojoConverters.internalToConnectionRead(standardSync)); - } - - return new ConnectionReadList().connections(connectionReads); - } - - public ConnectionRead getConnection(final UUID connectionId) - throws JsonValidationException, IOException, ConfigNotFoundException { - return buildConnectionRead(connectionId); - } - - public CatalogDiff getDiff(final AirbyteCatalog oldCatalog, final AirbyteCatalog newCatalog, final ConfiguredAirbyteCatalog configuredCatalog) - throws JsonValidationException { - return new CatalogDiff().transforms(CatalogHelpers.getCatalogDiff( - CatalogHelpers.configuredCatalogToCatalog(CatalogConverter.toProtocolKeepAllStreams(oldCatalog)), - CatalogHelpers.configuredCatalogToCatalog(CatalogConverter.toProtocolKeepAllStreams(newCatalog)), configuredCatalog) - .stream() - .map(CatalogDiffConverters::streamTransformToApi) - .toList()); - } - - /** - * Returns the list of the streamDescriptor that have their config updated. - * - * @param oldCatalog the old catalog - * @param newCatalog the new catalog - * @return the list of StreamDescriptor that have their configuration changed - */ - public Set getConfigurationDiff(final AirbyteCatalog oldCatalog, final AirbyteCatalog newCatalog) { - final Map oldStreams = catalogToPerStreamConfiguration(oldCatalog); - final Map newStreams = catalogToPerStreamConfiguration(newCatalog); - - final Set streamWithDifferentConf = new HashSet<>(); - - newStreams.forEach(((streamDescriptor, airbyteStreamConfiguration) -> { - final AirbyteStreamConfiguration oldConfig = oldStreams.get(streamDescriptor); - - if (oldConfig != null && haveConfigChange(oldConfig, airbyteStreamConfiguration)) { - streamWithDifferentConf.add(streamDescriptor); - } - })); - - return streamWithDifferentConf; - } - - private boolean haveConfigChange(final AirbyteStreamConfiguration oldConfig, final AirbyteStreamConfiguration newConfig) { - final List oldCursors = oldConfig.getCursorField(); - final List newCursors = newConfig.getCursorField(); - final boolean hasCursorChanged = !(oldCursors.equals(newCursors)); - - final boolean hasSyncModeChanged = !oldConfig.getSyncMode().equals(newConfig.getSyncMode()); - - final boolean hasDestinationSyncModeChanged = !oldConfig.getDestinationSyncMode().equals(newConfig.getDestinationSyncMode()); - - final Set> convertedOldPrimaryKey = new HashSet<>(oldConfig.getPrimaryKey()); - final Set> convertedNewPrimaryKey = new HashSet<>(newConfig.getPrimaryKey()); - final boolean hasPrimaryKeyChanged = !(convertedOldPrimaryKey.equals(convertedNewPrimaryKey)); - - return hasCursorChanged || hasSyncModeChanged || hasDestinationSyncModeChanged || hasPrimaryKeyChanged; - } - - private Map catalogToPerStreamConfiguration(final AirbyteCatalog catalog) { - return catalog.getStreams().stream().collect(Collectors.toMap(stream -> new StreamDescriptor() - .name(stream.getStream().getName()) - .namespace(stream.getStream().getNamespace()), - stream -> stream.getConfig())); - } - - public Optional getConnectionAirbyteCatalog(final UUID connectionId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSync connection = configRepository.getStandardSync(connectionId); - if (connection.getSourceCatalogId() == null) { - return Optional.empty(); - } - final ActorCatalog catalog = configRepository.getActorCatalogById(connection.getSourceCatalogId()); - final StandardSourceDefinition sourceDefinition = configRepository.getSourceDefinitionFromSource(connection.getSourceId()); - final io.airbyte.protocol.models.AirbyteCatalog jsonCatalog = Jsons.object(catalog.getCatalog(), io.airbyte.protocol.models.AirbyteCatalog.class); - return Optional.of(CatalogConverter.toApi(jsonCatalog, sourceDefinition)); - } - - public ConnectionReadList searchConnections(final ConnectionSearch connectionSearch) - throws JsonValidationException, IOException, ConfigNotFoundException { - final List reads = Lists.newArrayList(); - for (final StandardSync standardSync : configRepository.listStandardSyncs()) { - if (standardSync.getStatus() != StandardSync.Status.DEPRECATED) { - final ConnectionRead connectionRead = ApiPojoConverters.internalToConnectionRead(standardSync); - if (matchSearch(connectionSearch, connectionRead)) { - reads.add(connectionRead); - } - } - } - - return new ConnectionReadList().connections(reads); - } - - public boolean matchSearch(final ConnectionSearch connectionSearch, final ConnectionRead connectionRead) - throws JsonValidationException, ConfigNotFoundException, IOException { - - final SourceConnection sourceConnection = configRepository.getSourceConnection(connectionRead.getSourceId()); - final StandardSourceDefinition sourceDefinition = - configRepository.getStandardSourceDefinition(sourceConnection.getSourceDefinitionId()); - final SourceRead sourceRead = SourceHandler.toSourceRead(sourceConnection, sourceDefinition); - - final DestinationConnection destinationConnection = configRepository.getDestinationConnection(connectionRead.getDestinationId()); - final StandardDestinationDefinition destinationDefinition = - configRepository.getStandardDestinationDefinition(destinationConnection.getDestinationDefinitionId()); - final DestinationRead destinationRead = DestinationHandler.toDestinationRead(destinationConnection, destinationDefinition); - - final ConnectionMatcher connectionMatcher = new ConnectionMatcher(connectionSearch); - final ConnectionRead connectionReadFromSearch = connectionMatcher.match(connectionRead); - - return (connectionReadFromSearch == null || connectionReadFromSearch.equals(connectionRead)) && - matchSearch(connectionSearch.getSource(), sourceRead) && - matchSearch(connectionSearch.getDestination(), destinationRead); - } - - // todo (cgardens) - make this static. requires removing one bad dependency in SourceHandlerTest - public boolean matchSearch(final SourceSearch sourceSearch, final SourceRead sourceRead) { - final SourceMatcher sourceMatcher = new SourceMatcher(sourceSearch); - final SourceRead sourceReadFromSearch = sourceMatcher.match(sourceRead); - - return (sourceReadFromSearch == null || sourceReadFromSearch.equals(sourceRead)); - } - - // todo (cgardens) - make this static. requires removing one bad dependency in - // DestinationHandlerTest - public boolean matchSearch(final DestinationSearch destinationSearch, final DestinationRead destinationRead) { - final DestinationMatcher destinationMatcher = new DestinationMatcher(destinationSearch); - final DestinationRead destinationReadFromSearch = destinationMatcher.match(destinationRead); - - return (destinationReadFromSearch == null || destinationReadFromSearch.equals(destinationRead)); - } - - public void deleteConnection(final UUID connectionId) throws JsonValidationException, ConfigNotFoundException, IOException { - connectionHelper.deleteConnection(connectionId); - eventRunner.forceDeleteConnection(connectionId); - } - - private ConnectionRead buildConnectionRead(final UUID connectionId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSync standardSync = configRepository.getStandardSync(connectionId); - return ApiPojoConverters.internalToConnectionRead(standardSync); - } - - private static String getFrequencyStringFromScheduleType(final ScheduleType scheduleType, final ScheduleData scheduleData) { - switch (scheduleType) { - case MANUAL -> { - return "manual"; - } - case BASIC_SCHEDULE -> { - return TimeUnit.SECONDS.toMinutes(ScheduleHelpers.getIntervalInSecond(scheduleData.getBasicSchedule())) + " min"; - } - case CRON -> { - // TODO(https://github.com/airbytehq/airbyte/issues/2170): consider something more detailed. - return "cron"; - } - default -> { - throw new RuntimeException("Unexpected schedule type"); - } - } - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandler.java deleted file mode 100644 index 91fa73011270b..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandler.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.api.model.generated.CustomDestinationDefinitionCreate; -import io.airbyte.api.model.generated.DestinationDefinitionCreate; -import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.DestinationDefinitionRead; -import io.airbyte.api.model.generated.DestinationDefinitionReadList; -import io.airbyte.api.model.generated.DestinationDefinitionUpdate; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.PrivateDestinationDefinitionRead; -import io.airbyte.api.model.generated.PrivateDestinationDefinitionReadList; -import io.airbyte.api.model.generated.ReleaseStage; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.commons.server.ServerConstants; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.server.converters.SpecFetcher; -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.commons.server.errors.InternalServerKnownException; -import io.airbyte.commons.server.errors.UnsupportedProtocolVersionException; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.commons.util.MoreLists; -import io.airbyte.commons.version.AirbyteProtocolVersion; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorDefinitionResourceRequirements; -import io.airbyte.config.ActorType; -import io.airbyte.config.Configs; -import io.airbyte.config.EnvConfigs; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.time.LocalDate; -import java.util.List; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.UUID; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -@SuppressWarnings("PMD.AvoidCatchingNPE") -@Singleton -public class DestinationDefinitionsHandler { - - private final ConfigRepository configRepository; - private final Supplier uuidSupplier; - private final SynchronousSchedulerClient schedulerSynchronousClient; - private final AirbyteGithubStore githubStore; - private final DestinationHandler destinationHandler; - private final AirbyteProtocolVersionRange protocolVersionRange; - - @VisibleForTesting - public DestinationDefinitionsHandler(final ConfigRepository configRepository, - final Supplier uuidSupplier, - final SynchronousSchedulerClient schedulerSynchronousClient, - final AirbyteGithubStore githubStore, - final DestinationHandler destinationHandler, - final AirbyteProtocolVersionRange protocolVersionRange) { - this.configRepository = configRepository; - this.uuidSupplier = uuidSupplier; - this.schedulerSynchronousClient = schedulerSynchronousClient; - this.githubStore = githubStore; - this.destinationHandler = destinationHandler; - this.protocolVersionRange = protocolVersionRange; - } - - // This should be deleted when cloud is migrated to micronaut - @Deprecated(forRemoval = true) - public DestinationDefinitionsHandler(final ConfigRepository configRepository, - final SynchronousSchedulerClient schedulerSynchronousClient, - final DestinationHandler destinationHandler) { - this.configRepository = configRepository; - this.uuidSupplier = UUID::randomUUID; - this.schedulerSynchronousClient = schedulerSynchronousClient; - this.githubStore = AirbyteGithubStore.production(); - this.destinationHandler = destinationHandler; - final Configs configs = new EnvConfigs(); - this.protocolVersionRange = new AirbyteProtocolVersionRange(configs.getAirbyteProtocolVersionMin(), configs.getAirbyteProtocolVersionMax()); - } - - @VisibleForTesting - static DestinationDefinitionRead buildDestinationDefinitionRead(final StandardDestinationDefinition standardDestinationDefinition) { - try { - - return new DestinationDefinitionRead() - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .name(standardDestinationDefinition.getName()) - .dockerRepository(standardDestinationDefinition.getDockerRepository()) - .dockerImageTag(standardDestinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(standardDestinationDefinition.getDocumentationUrl())) - .icon(loadIcon(standardDestinationDefinition.getIcon())) - .protocolVersion(standardDestinationDefinition.getProtocolVersion()) - .releaseStage(getReleaseStage(standardDestinationDefinition)) - .releaseDate(getReleaseDate(standardDestinationDefinition)) - .supportsDbt(Objects.requireNonNullElse(standardDestinationDefinition.getSupportsDbt(), false)) - .normalizationConfig( - ApiPojoConverters.normalizationDestinationDefinitionConfigToApi(standardDestinationDefinition.getNormalizationConfig())) - .resourceRequirements(ApiPojoConverters.actorDefResourceReqsToApi(standardDestinationDefinition.getResourceRequirements())); - } catch (final URISyntaxException | NullPointerException e) { - throw new InternalServerKnownException("Unable to process retrieved latest destination definitions list", e); - } - } - - private static ReleaseStage getReleaseStage(final StandardDestinationDefinition standardDestinationDefinition) { - if (standardDestinationDefinition.getReleaseStage() == null) { - return null; - } - return ReleaseStage.fromValue(standardDestinationDefinition.getReleaseStage().value()); - } - - private static LocalDate getReleaseDate(final StandardDestinationDefinition standardDestinationDefinition) { - if (standardDestinationDefinition.getReleaseDate() == null || standardDestinationDefinition.getReleaseDate().isBlank()) { - return null; - } - - return LocalDate.parse(standardDestinationDefinition.getReleaseDate()); - } - - public DestinationDefinitionReadList listDestinationDefinitions() throws IOException, JsonValidationException { - return toDestinationDefinitionReadList(configRepository.listStandardDestinationDefinitions(false)); - } - - private static DestinationDefinitionReadList toDestinationDefinitionReadList(final List defs) { - final List reads = defs.stream() - .map(DestinationDefinitionsHandler::buildDestinationDefinitionRead) - .collect(Collectors.toList()); - return new DestinationDefinitionReadList().destinationDefinitions(reads); - } - - public DestinationDefinitionReadList listLatestDestinationDefinitions() { - return toDestinationDefinitionReadList(getLatestDestinations()); - } - - private List getLatestDestinations() { - try { - return githubStore.getLatestDestinations(); - } catch (final InterruptedException e) { - throw new InternalServerKnownException("Request to retrieve latest destination definitions failed", e); - } - } - - public DestinationDefinitionReadList listDestinationDefinitionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws IOException { - return toDestinationDefinitionReadList(MoreLists.concat( - configRepository.listPublicDestinationDefinitions(false), - configRepository.listGrantedDestinationDefinitions(workspaceIdRequestBody.getWorkspaceId(), false))); - } - - public PrivateDestinationDefinitionReadList listPrivateDestinationDefinitions(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws IOException { - final List> standardDestinationDefinitionBooleanMap = - configRepository.listGrantableDestinationDefinitions(workspaceIdRequestBody.getWorkspaceId(), false); - return toPrivateDestinationDefinitionReadList(standardDestinationDefinitionBooleanMap); - } - - private static PrivateDestinationDefinitionReadList toPrivateDestinationDefinitionReadList( - final List> defs) { - final List reads = defs.stream() - .map(entry -> new PrivateDestinationDefinitionRead() - .destinationDefinition(buildDestinationDefinitionRead(entry.getKey())) - .granted(entry.getValue())) - .collect(Collectors.toList()); - return new PrivateDestinationDefinitionReadList().destinationDefinitions(reads); - } - - public DestinationDefinitionRead getDestinationDefinition(final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - return buildDestinationDefinitionRead( - configRepository.getStandardDestinationDefinition(destinationDefinitionIdRequestBody.getDestinationDefinitionId())); - } - - public DestinationDefinitionRead getDestinationDefinitionForWorkspace( - final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final UUID definitionId = destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId(); - final UUID workspaceId = destinationDefinitionIdWithWorkspaceId.getWorkspaceId(); - if (!configRepository.workspaceCanUseDefinition(definitionId, workspaceId)) { - throw new IdNotFoundKnownException("Cannot find the requested definition with given id for this workspace", definitionId.toString()); - } - return getDestinationDefinition(new DestinationDefinitionIdRequestBody().destinationDefinitionId(definitionId)); - } - - public DestinationDefinitionRead createCustomDestinationDefinition(final CustomDestinationDefinitionCreate customDestinationDefinitionCreate) - throws IOException { - final StandardDestinationDefinition destinationDefinition = destinationDefinitionFromCreate( - customDestinationDefinitionCreate.getDestinationDefinition()) - .withPublic(false) - .withCustom(true); - if (!protocolVersionRange.isSupported(new Version(destinationDefinition.getProtocolVersion()))) { - throw new UnsupportedProtocolVersionException(destinationDefinition.getProtocolVersion(), protocolVersionRange.min(), - protocolVersionRange.max()); - } - configRepository.writeCustomDestinationDefinition(destinationDefinition, customDestinationDefinitionCreate.getWorkspaceId()); - - return buildDestinationDefinitionRead(destinationDefinition); - } - - private StandardDestinationDefinition destinationDefinitionFromCreate(final DestinationDefinitionCreate destinationDefCreate) throws IOException { - final ConnectorSpecification spec = getSpecForImage( - destinationDefCreate.getDockerRepository(), - destinationDefCreate.getDockerImageTag(), - // Only custom connectors can be created via handlers. - true); - - final Version airbyteProtocolVersion = AirbyteProtocolVersion.getWithDefault(spec.getProtocolVersion()); - - final UUID id = uuidSupplier.get(); - final StandardDestinationDefinition destinationDefinition = new StandardDestinationDefinition() - .withDestinationDefinitionId(id) - .withDockerRepository(destinationDefCreate.getDockerRepository()) - .withDockerImageTag(destinationDefCreate.getDockerImageTag()) - .withDocumentationUrl(destinationDefCreate.getDocumentationUrl().toString()) - .withName(destinationDefCreate.getName()) - .withIcon(destinationDefCreate.getIcon()) - .withSpec(spec) - .withProtocolVersion(airbyteProtocolVersion.serialize()) - .withTombstone(false) - .withReleaseStage(StandardDestinationDefinition.ReleaseStage.CUSTOM) - .withResourceRequirements(ApiPojoConverters.actorDefResourceReqsToInternal(destinationDefCreate.getResourceRequirements())); - return destinationDefinition; - } - - public DestinationDefinitionRead updateDestinationDefinition(final DestinationDefinitionUpdate destinationDefinitionUpdate) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardDestinationDefinition currentDestination = configRepository - .getStandardDestinationDefinition(destinationDefinitionUpdate.getDestinationDefinitionId()); - - // specs are re-fetched from the container if the image tag has changed, or if the tag is "dev", - // to allow for easier iteration of dev images - final boolean specNeedsUpdate = !currentDestination.getDockerImageTag().equals(destinationDefinitionUpdate.getDockerImageTag()) - || ServerConstants.DEV_IMAGE_TAG.equals(destinationDefinitionUpdate.getDockerImageTag()); - final ConnectorSpecification spec = specNeedsUpdate - ? getSpecForImage(currentDestination.getDockerRepository(), destinationDefinitionUpdate.getDockerImageTag(), currentDestination.getCustom()) - : currentDestination.getSpec(); - final ActorDefinitionResourceRequirements updatedResourceReqs = destinationDefinitionUpdate.getResourceRequirements() != null - ? ApiPojoConverters.actorDefResourceReqsToInternal(destinationDefinitionUpdate.getResourceRequirements()) - : currentDestination.getResourceRequirements(); - - final Version airbyteProtocolVersion = AirbyteProtocolVersion.getWithDefault(spec.getProtocolVersion()); - if (!protocolVersionRange.isSupported(airbyteProtocolVersion)) { - throw new UnsupportedProtocolVersionException(airbyteProtocolVersion, protocolVersionRange.min(), protocolVersionRange.max()); - } - - final StandardDestinationDefinition newDestination = new StandardDestinationDefinition() - .withDestinationDefinitionId(currentDestination.getDestinationDefinitionId()) - .withDockerImageTag(destinationDefinitionUpdate.getDockerImageTag()) - .withDockerRepository(currentDestination.getDockerRepository()) - .withName(currentDestination.getName()) - .withDocumentationUrl(currentDestination.getDocumentationUrl()) - .withIcon(currentDestination.getIcon()) - .withNormalizationConfig(currentDestination.getNormalizationConfig()) - .withSupportsDbt(currentDestination.getSupportsDbt()) - .withSpec(spec) - .withProtocolVersion(airbyteProtocolVersion.serialize()) - .withTombstone(currentDestination.getTombstone()) - .withPublic(currentDestination.getPublic()) - .withCustom(currentDestination.getCustom()) - .withReleaseStage(currentDestination.getReleaseStage()) - .withReleaseDate(currentDestination.getReleaseDate()) - .withResourceRequirements(updatedResourceReqs); - - configRepository.writeStandardDestinationDefinition(newDestination); - configRepository.clearUnsupportedProtocolVersionFlag(newDestination.getDestinationDefinitionId(), ActorType.DESTINATION, protocolVersionRange); - return buildDestinationDefinitionRead(newDestination); - } - - public void deleteDestinationDefinition(final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody) - throws JsonValidationException, ConfigNotFoundException, IOException { - // "delete" all destinations associated with the destination definition as well. This will cascade - // to connections that depend on any deleted - // destinations. Delete destinations first in case a failure occurs mid-operation. - - final StandardDestinationDefinition persistedDestinationDefinition = - configRepository.getStandardDestinationDefinition(destinationDefinitionIdRequestBody.getDestinationDefinitionId()); - - for (final DestinationRead destinationRead : destinationHandler.listDestinationsForDestinationDefinition(destinationDefinitionIdRequestBody) - .getDestinations()) { - destinationHandler.deleteDestination(destinationRead); - } - - persistedDestinationDefinition.withTombstone(true); - configRepository.writeStandardDestinationDefinition(persistedDestinationDefinition); - } - - private ConnectorSpecification getSpecForImage(final String dockerRepository, final String imageTag, final boolean isCustomConnector) - throws IOException { - final String imageName = dockerRepository + ":" + imageTag; - final SynchronousResponse getSpecResponse = schedulerSynchronousClient.createGetSpecJob(imageName, isCustomConnector); - return SpecFetcher.getSpecFromJob(getSpecResponse); - } - - public static String loadIcon(final String name) { - try { - return name == null ? null : MoreResources.readResource("icons/" + name); - } catch (final Exception e) { - return null; - } - } - - public PrivateDestinationDefinitionRead grantDestinationDefinitionToWorkspace( - final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardDestinationDefinition standardDestinationDefinition = - configRepository.getStandardDestinationDefinition(destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId()); - configRepository.writeActorDefinitionWorkspaceGrant( - destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId(), - destinationDefinitionIdWithWorkspaceId.getWorkspaceId()); - return new PrivateDestinationDefinitionRead() - .destinationDefinition(buildDestinationDefinitionRead(standardDestinationDefinition)) - .granted(true); - } - - public void revokeDestinationDefinitionFromWorkspace(final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) - throws IOException { - configRepository.deleteActorDefinitionWorkspaceGrant( - destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId(), - destinationDefinitionIdWithWorkspaceId.getWorkspaceId()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationHandler.java deleted file mode 100644 index 13471b10397cb..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/DestinationHandler.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.DestinationCloneConfiguration; -import io.airbyte.api.model.generated.DestinationCloneRequestBody; -import io.airbyte.api.model.generated.DestinationCreate; -import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationReadList; -import io.airbyte.api.model.generated.DestinationSearch; -import io.airbyte.api.model.generated.DestinationSnippetRead; -import io.airbyte.api.model.generated.DestinationUpdate; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.ConfigurationUpdate; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; - -@Singleton -public class DestinationHandler { - - private final ConnectionsHandler connectionsHandler; - private final Supplier uuidGenerator; - private final ConfigRepository configRepository; - private final SecretsRepositoryReader secretsRepositoryReader; - private final SecretsRepositoryWriter secretsRepositoryWriter; - private final JsonSchemaValidator validator; - private final ConfigurationUpdate configurationUpdate; - private final JsonSecretsProcessor secretsProcessor; - private final OAuthConfigSupplier oAuthConfigSupplier; - - @VisibleForTesting - DestinationHandler(final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final JsonSchemaValidator integrationSchemaValidation, - final ConnectionsHandler connectionsHandler, - final Supplier uuidGenerator, - final JsonSecretsProcessor secretsProcessor, - final ConfigurationUpdate configurationUpdate, - final OAuthConfigSupplier oAuthConfigSupplier) { - this.configRepository = configRepository; - this.secretsRepositoryReader = secretsRepositoryReader; - this.secretsRepositoryWriter = secretsRepositoryWriter; - validator = integrationSchemaValidation; - this.connectionsHandler = connectionsHandler; - this.uuidGenerator = uuidGenerator; - this.configurationUpdate = configurationUpdate; - this.secretsProcessor = secretsProcessor; - this.oAuthConfigSupplier = oAuthConfigSupplier; - } - - @Inject - public DestinationHandler(final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final JsonSchemaValidator integrationSchemaValidation, - final ConnectionsHandler connectionsHandler, - final OAuthConfigSupplier oAuthConfigSupplier) { - this( - configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - integrationSchemaValidation, - connectionsHandler, - UUID::randomUUID, - JsonSecretsProcessor.builder() - .copySecrets(true) - .build(), - new ConfigurationUpdate(configRepository, secretsRepositoryReader), - oAuthConfigSupplier); - } - - public DestinationRead createDestination(final DestinationCreate destinationCreate) - throws ConfigNotFoundException, IOException, JsonValidationException { - // validate configuration - final ConnectorSpecification spec = getSpec(destinationCreate.getDestinationDefinitionId()); - validateDestination(spec, destinationCreate.getConnectionConfiguration()); - - // persist - final UUID destinationId = uuidGenerator.get(); - persistDestinationConnection( - destinationCreate.getName() != null ? destinationCreate.getName() : "default", - destinationCreate.getDestinationDefinitionId(), - destinationCreate.getWorkspaceId(), - destinationId, - destinationCreate.getConnectionConfiguration(), - false); - - // read configuration from db - return buildDestinationRead(configRepository.getDestinationConnection(destinationId), spec); - } - - public void deleteDestination(final DestinationIdRequestBody destinationIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // get existing implementation - final DestinationRead destination = buildDestinationRead(destinationIdRequestBody.getDestinationId()); - - deleteDestination(destination); - } - - public void deleteDestination(final DestinationRead destination) - throws JsonValidationException, IOException, ConfigNotFoundException { - // disable all connections associated with this destination - // Delete connections first in case it fails in the middle, destination will still be visible - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(destination.getWorkspaceId()); - for (final ConnectionRead connectionRead : connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody).getConnections()) { - if (!connectionRead.getDestinationId().equals(destination.getDestinationId())) { - continue; - } - - connectionsHandler.deleteConnection(connectionRead.getConnectionId()); - } - - final var fullConfig = secretsRepositoryReader.getDestinationConnectionWithSecrets(destination.getDestinationId()).getConfiguration(); - - // persist - persistDestinationConnection( - destination.getName(), - destination.getDestinationDefinitionId(), - destination.getWorkspaceId(), - destination.getDestinationId(), - fullConfig, - true); - } - - public DestinationRead updateDestination(final DestinationUpdate destinationUpdate) - throws ConfigNotFoundException, IOException, JsonValidationException { - // get existing implementation - final DestinationConnection updatedDestination = configurationUpdate - .destination(destinationUpdate.getDestinationId(), destinationUpdate.getName(), destinationUpdate.getConnectionConfiguration()); - - final ConnectorSpecification spec = getSpec(updatedDestination.getDestinationDefinitionId()); - - // validate configuration - validateDestination(spec, updatedDestination.getConfiguration()); - - // persist - persistDestinationConnection( - updatedDestination.getName(), - updatedDestination.getDestinationDefinitionId(), - updatedDestination.getWorkspaceId(), - updatedDestination.getDestinationId(), - updatedDestination.getConfiguration(), - updatedDestination.getTombstone()); - - // read configuration from db - return buildDestinationRead( - configRepository.getDestinationConnection(destinationUpdate.getDestinationId()), spec); - } - - public DestinationRead getDestination(final DestinationIdRequestBody destinationIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - return buildDestinationRead(destinationIdRequestBody.getDestinationId()); - } - - public DestinationRead cloneDestination(final DestinationCloneRequestBody destinationCloneRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // read destination configuration from db - final DestinationRead destinationToClone = buildDestinationReadWithSecrets(destinationCloneRequestBody.getDestinationCloneId()); - final DestinationCloneConfiguration destinationCloneConfiguration = destinationCloneRequestBody.getDestinationConfiguration(); - - final String copyText = " (Copy)"; - final String destinationName = destinationToClone.getName() + copyText; - - final DestinationCreate destinationCreate = new DestinationCreate() - .name(destinationName) - .destinationDefinitionId(destinationToClone.getDestinationDefinitionId()) - .connectionConfiguration(destinationToClone.getConnectionConfiguration()) - .workspaceId(destinationToClone.getWorkspaceId()); - - if (destinationCloneConfiguration != null) { - if (destinationCloneConfiguration.getName() != null) { - destinationCreate.name(destinationCloneConfiguration.getName()); - } - - if (destinationCloneConfiguration.getConnectionConfiguration() != null) { - destinationCreate.connectionConfiguration(destinationCloneConfiguration.getConnectionConfiguration()); - } - } - - return createDestination(destinationCreate); - } - - public DestinationReadList listDestinationsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - - final List reads = Lists.newArrayList(); - for (final DestinationConnection dci : configRepository.listWorkspaceDestinationConnection(workspaceIdRequestBody.getWorkspaceId())) { - reads.add(buildDestinationRead(dci)); - } - return new DestinationReadList().destinations(reads); - } - - public DestinationReadList listDestinationsForDestinationDefinition(final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - final List reads = Lists.newArrayList(); - - for (final DestinationConnection destinationConnection : configRepository - .listDestinationsForDefinition(destinationDefinitionIdRequestBody.getDestinationDefinitionId())) { - reads.add(buildDestinationRead(destinationConnection)); - } - - return new DestinationReadList().destinations(reads); - } - - public DestinationReadList searchDestinations(final DestinationSearch destinationSearch) - throws ConfigNotFoundException, IOException, JsonValidationException { - final List reads = Lists.newArrayList(); - - for (final DestinationConnection dci : configRepository.listDestinationConnection()) { - if (!dci.getTombstone()) { - final DestinationRead destinationRead = buildDestinationRead(dci); - if (connectionsHandler.matchSearch(destinationSearch, destinationRead)) { - reads.add(destinationRead); - } - } - } - - return new DestinationReadList().destinations(reads); - } - - private void validateDestination(final ConnectorSpecification spec, final JsonNode configuration) throws JsonValidationException { - validator.ensure(spec.getConnectionSpecification(), configuration); - } - - public ConnectorSpecification getSpec(final UUID destinationDefinitionId) - throws JsonValidationException, IOException, ConfigNotFoundException { - return configRepository.getStandardDestinationDefinition(destinationDefinitionId).getSpec(); - } - - private void persistDestinationConnection(final String name, - final UUID destinationDefinitionId, - final UUID workspaceId, - final UUID destinationId, - final JsonNode configurationJson, - final boolean tombstone) - throws JsonValidationException, IOException, ConfigNotFoundException { - final JsonNode oAuthMaskedConfigurationJson = - oAuthConfigSupplier.maskDestinationOAuthParameters(destinationDefinitionId, workspaceId, configurationJson); - final DestinationConnection destinationConnection = new DestinationConnection() - .withName(name) - .withDestinationDefinitionId(destinationDefinitionId) - .withWorkspaceId(workspaceId) - .withDestinationId(destinationId) - .withConfiguration(oAuthMaskedConfigurationJson) - .withTombstone(tombstone); - secretsRepositoryWriter.writeDestinationConnection(destinationConnection, getSpec(destinationDefinitionId)); - } - - private DestinationRead buildDestinationRead(final UUID destinationId) throws JsonValidationException, IOException, ConfigNotFoundException { - return buildDestinationRead(configRepository.getDestinationConnection(destinationId)); - } - - private DestinationRead buildDestinationRead(final DestinationConnection destinationConnection) - throws JsonValidationException, IOException, ConfigNotFoundException { - final ConnectorSpecification spec = getSpec(destinationConnection.getDestinationDefinitionId()); - return buildDestinationRead(destinationConnection, spec); - } - - private DestinationRead buildDestinationRead(final DestinationConnection destinationConnection, final ConnectorSpecification spec) - throws ConfigNotFoundException, IOException, JsonValidationException { - - // remove secrets from config before returning the read - final DestinationConnection dci = Jsons.clone(destinationConnection); - dci.setConfiguration(secretsProcessor.prepareSecretsForOutput(dci.getConfiguration(), spec.getConnectionSpecification())); - - final StandardDestinationDefinition standardDestinationDefinition = - configRepository.getStandardDestinationDefinition(dci.getDestinationDefinitionId()); - return toDestinationRead(dci, standardDestinationDefinition); - } - - private DestinationRead buildDestinationReadWithSecrets(final UUID destinationId) - throws ConfigNotFoundException, IOException, JsonValidationException { - - // remove secrets from config before returning the read - final DestinationConnection dci = Jsons.clone(secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationId)); - final StandardDestinationDefinition standardDestinationDefinition = - configRepository.getStandardDestinationDefinition(dci.getDestinationDefinitionId()); - return toDestinationRead(dci, standardDestinationDefinition); - } - - protected static DestinationRead toDestinationRead(final DestinationConnection destinationConnection, - final StandardDestinationDefinition standardDestinationDefinition) { - return new DestinationRead() - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .destinationId(destinationConnection.getDestinationId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationDefinitionId(destinationConnection.getDestinationDefinitionId()) - .connectionConfiguration(destinationConnection.getConfiguration()) - .name(destinationConnection.getName()) - .destinationName(standardDestinationDefinition.getName()) - .icon(DestinationDefinitionsHandler.loadIcon(standardDestinationDefinition.getIcon())); - } - - protected static DestinationSnippetRead toDestinationSnippetRead(final DestinationConnection destinationConnection, - final StandardDestinationDefinition standardDestinationDefinition) { - return new DestinationSnippetRead() - .destinationId(destinationConnection.getDestinationId()) - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .destinationName(standardDestinationDefinition.getName()) - .icon(DestinationDefinitionsHandler.loadIcon(standardDestinationDefinition.getIcon())); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/HealthCheckHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/HealthCheckHandler.java deleted file mode 100644 index fc618c2dcdb58..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/HealthCheckHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.HealthCheckRead; -import io.airbyte.config.persistence.ConfigRepository; -import jakarta.inject.Named; -import jakarta.inject.Singleton; - -@Singleton -public class HealthCheckHandler { - - private final ConfigRepository repository; - - public HealthCheckHandler(@Named("configRepository") final ConfigRepository repository) { - this.repository = repository; - } - - public HealthCheckRead health() { - return new HealthCheckRead().available(repository.healthCheck()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/JobHistoryHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/JobHistoryHandler.java deleted file mode 100644 index e3a7d01665ef4..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/JobHistoryHandler.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.google.common.base.Preconditions; -import io.airbyte.api.model.generated.AttemptInfoRead; -import io.airbyte.api.model.generated.AttemptNormalizationStatusReadList; -import io.airbyte.api.model.generated.AttemptRead; -import io.airbyte.api.model.generated.AttemptStats; -import io.airbyte.api.model.generated.AttemptStreamStats; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.model.generated.DestinationDefinitionRead; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.JobDebugInfoRead; -import io.airbyte.api.model.generated.JobDebugRead; -import io.airbyte.api.model.generated.JobIdRequestBody; -import io.airbyte.api.model.generated.JobInfoLightRead; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.JobListRequestBody; -import io.airbyte.api.model.generated.JobOptionalRead; -import io.airbyte.api.model.generated.JobRead; -import io.airbyte.api.model.generated.JobReadList; -import io.airbyte.api.model.generated.JobWithAttemptsRead; -import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.model.generated.SourceDefinitionRead; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.converters.JobConverter; -import io.airbyte.commons.server.converters.WorkflowStateConverter; -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.JobConfig; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.JobPersistence.JobAttemptPair; -import io.airbyte.persistence.job.models.Job; -import io.airbyte.persistence.job.models.JobStatus; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; - -@Singleton -@Slf4j -public class JobHistoryHandler { - - private final ConnectionsHandler connectionsHandler; - private final SourceHandler sourceHandler; - private final DestinationHandler destinationHandler; - private final SourceDefinitionsHandler sourceDefinitionsHandler; - private final DestinationDefinitionsHandler destinationDefinitionsHandler; - public static final int DEFAULT_PAGE_SIZE = 200; - private final JobPersistence jobPersistence; - private final JobConverter jobConverter; - private final WorkflowStateConverter workflowStateConverter; - private final AirbyteVersion airbyteVersion; - private final TemporalClient temporalClient; - - public JobHistoryHandler(final JobPersistence jobPersistence, - final WorkerEnvironment workerEnvironment, - final LogConfigs logConfigs, - final ConnectionsHandler connectionsHandler, - final SourceHandler sourceHandler, - final SourceDefinitionsHandler sourceDefinitionsHandler, - final DestinationHandler destinationHandler, - final DestinationDefinitionsHandler destinationDefinitionsHandler, - final AirbyteVersion airbyteVersion, - final TemporalClient temporalClient) { - jobConverter = new JobConverter(workerEnvironment, logConfigs); - workflowStateConverter = new WorkflowStateConverter(); - this.jobPersistence = jobPersistence; - this.connectionsHandler = connectionsHandler; - this.sourceHandler = sourceHandler; - this.sourceDefinitionsHandler = sourceDefinitionsHandler; - this.destinationHandler = destinationHandler; - this.destinationDefinitionsHandler = destinationDefinitionsHandler; - this.airbyteVersion = airbyteVersion; - this.temporalClient = temporalClient; - } - - @Deprecated(forRemoval = true) - public JobHistoryHandler(final JobPersistence jobPersistence, - final WorkerEnvironment workerEnvironment, - final LogConfigs logConfigs, - final ConnectionsHandler connectionsHandler, - final SourceHandler sourceHandler, - final SourceDefinitionsHandler sourceDefinitionsHandler, - final DestinationHandler destinationHandler, - final DestinationDefinitionsHandler destinationDefinitionsHandler, - final AirbyteVersion airbyteVersion) { - this(jobPersistence, workerEnvironment, logConfigs, connectionsHandler, sourceHandler, sourceDefinitionsHandler, destinationHandler, - destinationDefinitionsHandler, airbyteVersion, null); - } - - @SuppressWarnings("UnstableApiUsage") - public JobReadList listJobsFor(final JobListRequestBody request) throws IOException { - Preconditions.checkNotNull(request.getConfigTypes(), "configType cannot be null."); - Preconditions.checkState(!request.getConfigTypes().isEmpty(), "Must include at least one configType."); - - final Set configTypes = request.getConfigTypes() - .stream() - .map(type -> Enums.convertTo(type, JobConfig.ConfigType.class)) - .collect(Collectors.toSet()); - final String configId = request.getConfigId(); - - final int pageSize = (request.getPagination() != null && request.getPagination().getPageSize() != null) ? request.getPagination().getPageSize() - : DEFAULT_PAGE_SIZE; - final List jobs; - - if (request.getIncludingJobId() != null) { - jobs = jobPersistence.listJobsIncludingId(configTypes, configId, request.getIncludingJobId(), pageSize); - } else { - jobs = jobPersistence.listJobs(configTypes, configId, pageSize, - (request.getPagination() != null && request.getPagination().getRowOffset() != null) ? request.getPagination().getRowOffset() : 0); - } - - final List jobReads = jobs.stream().map(JobConverter::getJobWithAttemptsRead).collect(Collectors.toList()); - final var jobIds = jobReads.stream().map(r -> r.getJob().getId()).toList(); - final Map stats = jobPersistence.getAttemptStats(jobIds); - for (final JobWithAttemptsRead jwar : jobReads) { - for (final AttemptRead a : jwar.getAttempts()) { - final var stat = stats.get(new JobAttemptPair(jwar.getJob().getId(), a.getId().intValue())); - if (stat == null) { - log.error("Missing stats for job {} attempt {}", jwar.getJob().getId(), a.getId().intValue()); - continue; - } - - hydrateWithStats(a, stat); - } - } - - final Long totalJobCount = jobPersistence.getJobCount(configTypes, configId); - return new JobReadList().jobs(jobReads).totalJobCount(totalJobCount); - } - - /** - * Retrieve stats for a given job id and attempt number and hydrate the api model with the retrieved - * information. - * - * @param jobId the job the attempt belongs to. Used as an index to retrieve stats. - * @param a the attempt to hydrate stats for. - */ - private void hydrateWithStats(final AttemptRead a, final JobPersistence.AttemptStats attemptStats) { - a.setTotalStats(new AttemptStats()); - - final var combinedStats = attemptStats.combinedStats(); - if (combinedStats == null) { - // If overall stats are missing, assume stream stats are also missing, since overall stats are - // easier to produce than stream stats. Exit early. - return; - } - - a.getTotalStats() - .estimatedBytes(combinedStats.getEstimatedBytes()) - .estimatedRecords(combinedStats.getEstimatedRecords()) - .bytesEmitted(combinedStats.getBytesEmitted()) - .recordsEmitted(combinedStats.getRecordsEmitted()) - .recordsCommitted(combinedStats.getRecordsCommitted()); - - final var streamStats = attemptStats.perStreamStats().stream().map(s -> new AttemptStreamStats() - .streamName(s.getStreamName()) - .streamNamespace(s.getStreamNamespace()) - .stats(new AttemptStats() - .bytesEmitted(s.getStats().getBytesEmitted()) - .recordsEmitted(s.getStats().getRecordsEmitted()) - .recordsCommitted(s.getStats().getRecordsCommitted()) - .estimatedBytes(s.getStats().getEstimatedBytes()) - .estimatedRecords(s.getStats().getEstimatedRecords()))) - .collect(Collectors.toList()); - a.setStreamStats(streamStats); - } - - public JobInfoRead getJobInfo(final JobIdRequestBody jobIdRequestBody) throws IOException { - final Job job = jobPersistence.getJob(jobIdRequestBody.getId()); - return jobConverter.getJobInfoRead(job); - } - - public JobInfoLightRead getJobInfoLight(final JobIdRequestBody jobIdRequestBody) throws IOException { - final Job job = jobPersistence.getJob(jobIdRequestBody.getId()); - return jobConverter.getJobInfoLightRead(job); - } - - public JobOptionalRead getLastReplicationJob(final ConnectionIdRequestBody connectionIdRequestBody) throws IOException { - Optional job = jobPersistence.getLastReplicationJob(connectionIdRequestBody.getConnectionId()); - if (job.isEmpty()) { - return new JobOptionalRead(); - } else { - return jobConverter.getJobOptionalRead(job.get()); - } - - } - - public JobDebugInfoRead getJobDebugInfo(final JobIdRequestBody jobIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - final Job job = jobPersistence.getJob(jobIdRequestBody.getId()); - final JobInfoRead jobinfoRead = jobConverter.getJobInfoRead(job); - - for (final AttemptInfoRead a : jobinfoRead.getAttempts()) { - final int attemptNumber = a.getAttempt().getId().intValue(); - final var attemptStats = jobPersistence.getAttemptStats(job.getId(), attemptNumber); - hydrateWithStats(a.getAttempt(), attemptStats); - } - - final JobDebugInfoRead jobDebugInfoRead = buildJobDebugInfoRead(jobinfoRead); - if (temporalClient != null) { - final UUID connectionId = UUID.fromString(job.getScope()); - temporalClient.getWorkflowState(connectionId) - .map(workflowStateConverter::getWorkflowStateRead) - .ifPresent(jobDebugInfoRead::setWorkflowState); - } - - return jobDebugInfoRead; - } - - public Optional getLatestRunningSyncJob(final UUID connectionId) throws IOException { - final List nonTerminalSyncJobsForConnection = jobPersistence.listJobsForConnectionWithStatuses( - connectionId, - Collections.singleton(ConfigType.SYNC), - JobStatus.NON_TERMINAL_STATUSES); - - // there *should* only be a single running sync job for a connection, but - // jobPersistence.listJobsForConnectionWithStatuses orders by created_at desc so - // .findFirst will always return what we want. - return nonTerminalSyncJobsForConnection.stream().map(JobConverter::getJobRead).findFirst(); - } - - public Optional getLatestSyncJob(final UUID connectionId) throws IOException { - return jobPersistence.getLastSyncJob(connectionId).map(JobConverter::getJobRead); - } - - public List getLatestSyncJobsForConnections(final List connectionIds) throws IOException { - return jobPersistence.getLastSyncJobForConnections(connectionIds).stream() - .map(JobConverter::getJobRead) - .collect(Collectors.toList()); - } - - public AttemptNormalizationStatusReadList getAttemptNormalizationStatuses(final JobIdRequestBody jobIdRequestBody) throws IOException { - return new AttemptNormalizationStatusReadList() - .attemptNormalizationStatuses(jobPersistence.getAttemptNormalizationStatusesForJob(jobIdRequestBody.getId()).stream() - .map(JobConverter::convertAttemptNormalizationStatus).collect(Collectors.toList())); - } - - public List getRunningSyncJobForConnections(final List connectionIds) throws IOException { - return jobPersistence.getRunningSyncJobForConnections(connectionIds).stream() - .map(JobConverter::getJobRead) - .collect(Collectors.toList()); - } - - private SourceRead getSourceRead(final ConnectionRead connectionRead) throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(connectionRead.getSourceId()); - return sourceHandler.getSource(sourceIdRequestBody); - } - - private DestinationRead getDestinationRead(final ConnectionRead connectionRead) - throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody().destinationId(connectionRead.getDestinationId()); - return destinationHandler.getDestination(destinationIdRequestBody); - } - - private SourceDefinitionRead getSourceDefinitionRead(final SourceRead sourceRead) - throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody = - new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceRead.getSourceDefinitionId()); - return sourceDefinitionsHandler.getSourceDefinition(sourceDefinitionIdRequestBody); - } - - private DestinationDefinitionRead getDestinationDefinitionRead(final DestinationRead destinationRead) - throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody = - new DestinationDefinitionIdRequestBody().destinationDefinitionId(destinationRead.getDestinationDefinitionId()); - return destinationDefinitionsHandler.getDestinationDefinition(destinationDefinitionIdRequestBody); - } - - private JobDebugInfoRead buildJobDebugInfoRead(final JobInfoRead jobInfoRead) - throws ConfigNotFoundException, IOException, JsonValidationException { - final String configId = jobInfoRead.getJob().getConfigId(); - final ConnectionRead connection = connectionsHandler.getConnection(UUID.fromString(configId)); - final SourceRead source = getSourceRead(connection); - final DestinationRead destination = getDestinationRead(connection); - final SourceDefinitionRead sourceDefinitionRead = getSourceDefinitionRead(source); - final DestinationDefinitionRead destinationDefinitionRead = getDestinationDefinitionRead(destination); - final JobDebugRead jobDebugRead = JobConverter.getDebugJobInfoRead(jobInfoRead, sourceDefinitionRead, destinationDefinitionRead, airbyteVersion); - - return new JobDebugInfoRead() - .attempts(jobInfoRead.getAttempts()) - .job(jobDebugRead); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/LogsHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/LogsHandler.java deleted file mode 100644 index 2aa8ea5161e52..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/LogsHandler.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.LogsRequestBody; -import io.airbyte.config.Configs; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.helpers.LogClientSingleton; -import io.airbyte.config.helpers.LogConfigs; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.File; -import java.nio.file.Path; - -/** - * This handler is only responsible for server and scheduler logs. Jobs logs paths are determined by - * the submitJob function in the JobSubmitter class in the airbyte-server module. - */ -@Singleton -public class LogsHandler { - - private final Path workspaceRoot; - private final WorkerEnvironment workerEnvironment; - private final LogConfigs logConfigs; - - @Deprecated(forRemoval = true) - public LogsHandler(final Configs configs) { - this(configs.getWorkspaceRoot(), configs.getWorkerEnvironment(), configs.getLogConfigs()); - } - - @Inject - public LogsHandler(@Named("workspaceRoot") final Path workspaceRoot, - final WorkerEnvironment workerEnvironment, - final LogConfigs logConfigs) { - this.workspaceRoot = workspaceRoot; - this.workerEnvironment = workerEnvironment; - this.logConfigs = logConfigs; - } - - public File getLogs(final LogsRequestBody logsRequestBody) { - switch (logsRequestBody.getLogType()) { - case SERVER -> { - return LogClientSingleton.getInstance().getServerLogFile(workspaceRoot, workerEnvironment, logConfigs); - } - case SCHEDULER -> { - return LogClientSingleton.getInstance().getSchedulerLogFile(workspaceRoot, workerEnvironment, logConfigs); - } - default -> throw new IllegalStateException("Unexpected value: " + logsRequestBody.getLogType()); - } - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java deleted file mode 100644 index adbea35e36c11..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OAuthHandler.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.DESTINATION_DEFINITION_ID_KEY; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.SOURCE_DEFINITION_ID_KEY; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.WORKSPACE_ID_KEY; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.analytics.TrackingClient; -import io.airbyte.api.model.generated.CompleteDestinationOAuthRequest; -import io.airbyte.api.model.generated.CompleteSourceOauthRequest; -import io.airbyte.api.model.generated.DestinationOauthConsentRequest; -import io.airbyte.api.model.generated.OAuthConsentRead; -import io.airbyte.api.model.generated.SetInstancewideDestinationOauthParamsRequestBody; -import io.airbyte.api.model.generated.SetInstancewideSourceOauthParamsRequestBody; -import io.airbyte.api.model.generated.SourceOauthConsentRequest; -import io.airbyte.commons.constants.AirbyteSecretConstants; -import io.airbyte.commons.json.JsonPaths; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.handlers.helpers.OAuthPathExtractor; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.DestinationOAuthParameter; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.SourceOAuthParameter; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.metrics.lib.ApmTraceUtils; -import io.airbyte.oauth.OAuthFlowImplementation; -import io.airbyte.oauth.OAuthImplementationFactory; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.persistence.job.tracker.TrackingMetadata; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.net.http.HttpClient; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class OAuthHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(OAuthHandler.class); - private static final String ERROR_MESSAGE = "failed while reporting usage."; - - private final ConfigRepository configRepository; - private final OAuthImplementationFactory oAuthImplementationFactory; - private final TrackingClient trackingClient; - private final SecretsRepositoryReader secretsRepositoryReader; - - public OAuthHandler(final ConfigRepository configRepository, - final HttpClient httpClient, - final TrackingClient trackingClient, - final SecretsRepositoryReader secretsRepositoryReader) { - this.configRepository = configRepository; - this.oAuthImplementationFactory = new OAuthImplementationFactory(configRepository, httpClient); - this.trackingClient = trackingClient; - this.secretsRepositoryReader = secretsRepositoryReader; - } - - public OAuthConsentRead getSourceOAuthConsent(final SourceOauthConsentRequest sourceOauthConsentRequest) - throws JsonValidationException, ConfigNotFoundException, IOException { - final Map traceTags = Map.of(WORKSPACE_ID_KEY, sourceOauthConsentRequest.getWorkspaceId(), SOURCE_DEFINITION_ID_KEY, - sourceOauthConsentRequest.getSourceDefinitionId()); - ApmTraceUtils.addTagsToTrace(traceTags); - ApmTraceUtils.addTagsToRootSpan(traceTags); - final StandardSourceDefinition sourceDefinition = - configRepository.getStandardSourceDefinition(sourceOauthConsentRequest.getSourceDefinitionId()); - final OAuthFlowImplementation oAuthFlowImplementation = oAuthImplementationFactory.create(sourceDefinition); - final ConnectorSpecification spec = sourceDefinition.getSpec(); - final Map metadata = generateSourceMetadata(sourceOauthConsentRequest.getSourceDefinitionId()); - final OAuthConsentRead result; - if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { - final JsonNode oAuthInputConfigurationForConsent; - - if (sourceOauthConsentRequest.getSourceId() == null) { - oAuthInputConfigurationForConsent = sourceOauthConsentRequest.getoAuthInputConfiguration(); - } else { - final SourceConnection hydratedSourceConnection = - secretsRepositoryReader.getSourceConnectionWithSecrets(sourceOauthConsentRequest.getSourceId()); - - oAuthInputConfigurationForConsent = getOAuthInputConfigurationForConsent(spec, - hydratedSourceConnection.getConfiguration(), - sourceOauthConsentRequest.getoAuthInputConfiguration()); - } - - result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getSourceConsentUrl( - sourceOauthConsentRequest.getWorkspaceId(), - sourceOauthConsentRequest.getSourceDefinitionId(), - sourceOauthConsentRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification())); - } else { - result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getSourceConsentUrl( - sourceOauthConsentRequest.getWorkspaceId(), - sourceOauthConsentRequest.getSourceDefinitionId(), - sourceOauthConsentRequest.getRedirectUrl(), Jsons.emptyObject(), null)); - } - try { - trackingClient.track(sourceOauthConsentRequest.getWorkspaceId(), "Get Oauth Consent URL - Backend", metadata); - } catch (final Exception e) { - LOGGER.error(ERROR_MESSAGE, e); - } - return result; - } - - public OAuthConsentRead getDestinationOAuthConsent(final DestinationOauthConsentRequest destinationOauthConsentRequest) - throws JsonValidationException, ConfigNotFoundException, IOException { - final Map traceTags = Map.of(WORKSPACE_ID_KEY, destinationOauthConsentRequest.getWorkspaceId(), DESTINATION_DEFINITION_ID_KEY, - destinationOauthConsentRequest.getDestinationDefinitionId()); - ApmTraceUtils.addTagsToTrace(traceTags); - ApmTraceUtils.addTagsToRootSpan(traceTags); - - final StandardDestinationDefinition destinationDefinition = - configRepository.getStandardDestinationDefinition(destinationOauthConsentRequest.getDestinationDefinitionId()); - final OAuthFlowImplementation oAuthFlowImplementation = oAuthImplementationFactory.create(destinationDefinition); - final ConnectorSpecification spec = destinationDefinition.getSpec(); - final Map metadata = generateDestinationMetadata(destinationOauthConsentRequest.getDestinationDefinitionId()); - final OAuthConsentRead result; - if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { - final JsonNode oAuthInputConfigurationForConsent; - - if (destinationOauthConsentRequest.getDestinationId() == null) { - oAuthInputConfigurationForConsent = destinationOauthConsentRequest.getoAuthInputConfiguration(); - } else { - final DestinationConnection hydratedSourceConnection = - secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationOauthConsentRequest.getDestinationId()); - - oAuthInputConfigurationForConsent = getOAuthInputConfigurationForConsent(spec, - hydratedSourceConnection.getConfiguration(), - destinationOauthConsentRequest.getoAuthInputConfiguration()); - - } - - result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getDestinationConsentUrl( - destinationOauthConsentRequest.getWorkspaceId(), - destinationOauthConsentRequest.getDestinationDefinitionId(), - destinationOauthConsentRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification())); - } else { - result = new OAuthConsentRead().consentUrl(oAuthFlowImplementation.getDestinationConsentUrl( - destinationOauthConsentRequest.getWorkspaceId(), - destinationOauthConsentRequest.getDestinationDefinitionId(), - destinationOauthConsentRequest.getRedirectUrl(), Jsons.emptyObject(), null)); - } - try { - trackingClient.track(destinationOauthConsentRequest.getWorkspaceId(), "Get Oauth Consent URL - Backend", metadata); - } catch (final Exception e) { - LOGGER.error(ERROR_MESSAGE, e); - } - return result; - } - - public Map completeSourceOAuth(final CompleteSourceOauthRequest completeSourceOauthRequest) - throws JsonValidationException, ConfigNotFoundException, IOException { - final Map traceTags = Map.of(WORKSPACE_ID_KEY, completeSourceOauthRequest.getWorkspaceId(), SOURCE_DEFINITION_ID_KEY, - completeSourceOauthRequest.getSourceDefinitionId()); - ApmTraceUtils.addTagsToTrace(traceTags); - ApmTraceUtils.addTagsToRootSpan(traceTags); - - final StandardSourceDefinition sourceDefinition = - configRepository.getStandardSourceDefinition(completeSourceOauthRequest.getSourceDefinitionId()); - final OAuthFlowImplementation oAuthFlowImplementation = oAuthImplementationFactory.create(sourceDefinition); - final ConnectorSpecification spec = sourceDefinition.getSpec(); - final Map metadata = generateSourceMetadata(completeSourceOauthRequest.getSourceDefinitionId()); - final Map result; - if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { - final JsonNode oAuthInputConfigurationForConsent; - - if (completeSourceOauthRequest.getSourceId() == null) { - oAuthInputConfigurationForConsent = completeSourceOauthRequest.getoAuthInputConfiguration(); - } else { - final SourceConnection hydratedSourceConnection = - secretsRepositoryReader.getSourceConnectionWithSecrets(completeSourceOauthRequest.getSourceId()); - - oAuthInputConfigurationForConsent = getOAuthInputConfigurationForConsent(spec, - hydratedSourceConnection.getConfiguration(), - completeSourceOauthRequest.getoAuthInputConfiguration()); - } - - result = oAuthFlowImplementation.completeSourceOAuth( - completeSourceOauthRequest.getWorkspaceId(), - completeSourceOauthRequest.getSourceDefinitionId(), - completeSourceOauthRequest.getQueryParams(), - completeSourceOauthRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification()); - } else { - // deprecated but this path is kept for connectors that don't define OAuth Spec yet - result = oAuthFlowImplementation.completeSourceOAuth( - completeSourceOauthRequest.getWorkspaceId(), - completeSourceOauthRequest.getSourceDefinitionId(), - completeSourceOauthRequest.getQueryParams(), - completeSourceOauthRequest.getRedirectUrl()); - } - try { - trackingClient.track(completeSourceOauthRequest.getWorkspaceId(), "Complete OAuth Flow - Backend", metadata); - } catch (final Exception e) { - LOGGER.error(ERROR_MESSAGE, e); - } - return result; - } - - public Map completeDestinationOAuth(final CompleteDestinationOAuthRequest completeDestinationOAuthRequest) - throws JsonValidationException, ConfigNotFoundException, IOException { - final Map traceTags = Map.of(WORKSPACE_ID_KEY, completeDestinationOAuthRequest.getWorkspaceId(), DESTINATION_DEFINITION_ID_KEY, - completeDestinationOAuthRequest.getDestinationDefinitionId()); - ApmTraceUtils.addTagsToTrace(traceTags); - ApmTraceUtils.addTagsToRootSpan(traceTags); - - final StandardDestinationDefinition destinationDefinition = - configRepository.getStandardDestinationDefinition(completeDestinationOAuthRequest.getDestinationDefinitionId()); - final OAuthFlowImplementation oAuthFlowImplementation = oAuthImplementationFactory.create(destinationDefinition); - final ConnectorSpecification spec = destinationDefinition.getSpec(); - final Map metadata = generateDestinationMetadata(completeDestinationOAuthRequest.getDestinationDefinitionId()); - final Map result; - if (OAuthConfigSupplier.hasOAuthConfigSpecification(spec)) { - final JsonNode oAuthInputConfigurationForConsent; - - if (completeDestinationOAuthRequest.getDestinationId() == null) { - oAuthInputConfigurationForConsent = completeDestinationOAuthRequest.getoAuthInputConfiguration(); - } else { - final DestinationConnection hydratedSourceConnection = - secretsRepositoryReader.getDestinationConnectionWithSecrets(completeDestinationOAuthRequest.getDestinationId()); - - oAuthInputConfigurationForConsent = getOAuthInputConfigurationForConsent(spec, - hydratedSourceConnection.getConfiguration(), - completeDestinationOAuthRequest.getoAuthInputConfiguration()); - - } - - result = oAuthFlowImplementation.completeDestinationOAuth( - completeDestinationOAuthRequest.getWorkspaceId(), - completeDestinationOAuthRequest.getDestinationDefinitionId(), - completeDestinationOAuthRequest.getQueryParams(), - completeDestinationOAuthRequest.getRedirectUrl(), - oAuthInputConfigurationForConsent, - spec.getAdvancedAuth().getOauthConfigSpecification()); - } else { - // deprecated but this path is kept for connectors that don't define OAuth Spec yet - result = oAuthFlowImplementation.completeDestinationOAuth( - completeDestinationOAuthRequest.getWorkspaceId(), - completeDestinationOAuthRequest.getDestinationDefinitionId(), - completeDestinationOAuthRequest.getQueryParams(), - completeDestinationOAuthRequest.getRedirectUrl()); - } - try { - trackingClient.track(completeDestinationOAuthRequest.getWorkspaceId(), "Complete OAuth Flow - Backend", metadata); - } catch (final Exception e) { - LOGGER.error(ERROR_MESSAGE, e); - } - return result; - } - - public void setSourceInstancewideOauthParams(final SetInstancewideSourceOauthParamsRequestBody requestBody) - throws JsonValidationException, IOException { - final SourceOAuthParameter param = configRepository - .getSourceOAuthParamByDefinitionIdOptional(null, requestBody.getSourceDefinitionId()) - .orElseGet(() -> new SourceOAuthParameter().withOauthParameterId(UUID.randomUUID())) - .withConfiguration(Jsons.jsonNode(requestBody.getParams())) - .withSourceDefinitionId(requestBody.getSourceDefinitionId()); - // TODO validate requestBody.getParams() against - // spec.getAdvancedAuth().getOauthConfigSpecification().getCompleteOauthServerInputSpecification() - configRepository.writeSourceOAuthParam(param); - } - - public void setDestinationInstancewideOauthParams(final SetInstancewideDestinationOauthParamsRequestBody requestBody) - throws JsonValidationException, IOException { - final DestinationOAuthParameter param = configRepository - .getDestinationOAuthParamByDefinitionIdOptional(null, requestBody.getDestinationDefinitionId()) - .orElseGet(() -> new DestinationOAuthParameter().withOauthParameterId(UUID.randomUUID())) - .withConfiguration(Jsons.jsonNode(requestBody.getParams())) - .withDestinationDefinitionId(requestBody.getDestinationDefinitionId()); - // TODO validate requestBody.getParams() against - // spec.getAdvancedAuth().getOauthConfigSpecification().getCompleteOauthServerInputSpecification() - configRepository.writeDestinationOAuthParam(param); - } - - private JsonNode getOAuthInputConfigurationForConsent(final ConnectorSpecification spec, - final JsonNode hydratedSourceConnectionConfiguration, - final JsonNode oAuthInputConfiguration) { - final Map fieldsToGet = - buildJsonPathFromOAuthFlowInitParameters(OAuthPathExtractor.extractOauthConfigurationPaths( - spec.getAdvancedAuth().getOauthConfigSpecification().getOauthUserInputFromConnectorConfigSpecification())); - - final JsonNode oAuthInputConfigurationFromDB = getOAuthInputConfiguration(hydratedSourceConnectionConfiguration, fieldsToGet); - - return getOauthFromDBIfNeeded(oAuthInputConfigurationFromDB, - oAuthInputConfiguration); - } - - private Map generateSourceMetadata(final UUID sourceDefinitionId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSourceDefinition sourceDefinition = configRepository.getStandardSourceDefinition(sourceDefinitionId); - return TrackingMetadata.generateSourceDefinitionMetadata(sourceDefinition); - } - - private Map generateDestinationMetadata(final UUID destinationDefinitionId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardDestinationDefinition destinationDefinition = configRepository.getStandardDestinationDefinition(destinationDefinitionId); - return TrackingMetadata.generateDestinationDefinitionMetadata(destinationDefinition); - } - - @VisibleForTesting - Map buildJsonPathFromOAuthFlowInitParameters(final Map> oAuthFlowInitParameters) { - return oAuthFlowInitParameters.entrySet().stream() - .map(entry -> Map.entry(entry.getKey(), "$." + String.join(".", entry.getValue()))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - @VisibleForTesting - JsonNode getOauthFromDBIfNeeded(final JsonNode oAuthInputConfigurationFromDB, final JsonNode oAuthInputConfigurationFromInput) { - final ObjectNode result = (ObjectNode) Jsons.emptyObject(); - - oAuthInputConfigurationFromInput.fields().forEachRemaining(entry -> { - final String k = entry.getKey(); - final JsonNode v = entry.getValue(); - - // Note: This does not currently handle replacing masked secrets within nested objects. - if (AirbyteSecretConstants.SECRETS_MASK.equals(v.textValue())) { - if (oAuthInputConfigurationFromDB.has(k)) { - result.set(k, oAuthInputConfigurationFromDB.get(k)); - } else { - LOGGER.warn("Missing the key {} in the config store in DB", k); - } - } else { - result.set(k, v); - } - }); - - return result; - } - - @VisibleForTesting - JsonNode getOAuthInputConfiguration(final JsonNode hydratedSourceConnectionConfiguration, final Map pathsToGet) { - final Map result = new HashMap<>(); - pathsToGet.forEach((k, v) -> { - final Optional configValue = JsonPaths.getSingleValue(hydratedSourceConnectionConfiguration, v); - if (configValue.isPresent()) { - result.put(k, configValue.get()); - } else { - LOGGER.warn("Missing the key {} from the config stored in DB", k); - } - }); - - return Jsons.jsonNode(result); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OpenApiConfigHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OpenApiConfigHandler.java deleted file mode 100644 index 32a3fa70accd4..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OpenApiConfigHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.commons.resources.MoreResources; -import jakarta.inject.Singleton; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; - -@Singleton -public class OpenApiConfigHandler { - - private static final File TMP_FILE; - - static { - try { - TMP_FILE = File.createTempFile("airbyte", "openapiconfig"); - TMP_FILE.deleteOnExit(); - Files.writeString(TMP_FILE.toPath(), MoreResources.readResource("config.yaml")); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - - public File getFile() { - return TMP_FILE; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OperationsHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OperationsHandler.java deleted file mode 100644 index 21b793e69fc13..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/OperationsHandler.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.CheckOperationRead; -import io.airbyte.api.model.generated.CheckOperationRead.StatusEnum; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.OperationCreate; -import io.airbyte.api.model.generated.OperationIdRequestBody; -import io.airbyte.api.model.generated.OperationRead; -import io.airbyte.api.model.generated.OperationReadList; -import io.airbyte.api.model.generated.OperationUpdate; -import io.airbyte.api.model.generated.OperatorConfiguration; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.converters.OperationsConverter; -import io.airbyte.config.ConfigSchema; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSyncOperation; -import io.airbyte.config.StandardSyncOperation.OperatorType; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; - -@Singleton -public class OperationsHandler { - - private final ConfigRepository configRepository; - private final Supplier uuidGenerator; - - @Inject - public OperationsHandler(final ConfigRepository configRepository) { - this(configRepository, UUID::randomUUID); - } - - @VisibleForTesting - OperationsHandler(final ConfigRepository configRepository, final Supplier uuidGenerator) { - this.configRepository = configRepository; - this.uuidGenerator = uuidGenerator; - } - - public CheckOperationRead checkOperation(final OperatorConfiguration operationCheck) { - try { - validateOperation(operationCheck); - } catch (final IllegalArgumentException e) { - return new CheckOperationRead().status(StatusEnum.FAILED) - .message(e.getMessage()); - } - return new CheckOperationRead().status(StatusEnum.SUCCEEDED); - } - - public OperationRead createOperation(final OperationCreate operationCreate) - throws JsonValidationException, IOException, ConfigNotFoundException { - final UUID operationId = uuidGenerator.get(); - final StandardSyncOperation standardSyncOperation = toStandardSyncOperation(operationCreate) - .withOperationId(operationId); - return persistOperation(standardSyncOperation); - } - - private StandardSyncOperation toStandardSyncOperation(final OperationCreate operationCreate) { - final StandardSyncOperation standardSyncOperation = new StandardSyncOperation() - .withWorkspaceId(operationCreate.getWorkspaceId()) - .withName(operationCreate.getName()) - .withOperatorType(Enums.convertTo(operationCreate.getOperatorConfiguration().getOperatorType(), OperatorType.class)) - .withTombstone(false); - OperationsConverter.populateOperatorConfigFromApi(operationCreate.getOperatorConfiguration(), standardSyncOperation); - return standardSyncOperation; - } - - private void validateOperation(final OperatorConfiguration operatorConfiguration) { - if ((io.airbyte.api.model.generated.OperatorType.NORMALIZATION).equals(operatorConfiguration.getOperatorType())) { - Preconditions.checkArgument(operatorConfiguration.getNormalization() != null); - } - if ((io.airbyte.api.model.generated.OperatorType.DBT).equals(operatorConfiguration.getOperatorType())) { - Preconditions.checkArgument(operatorConfiguration.getDbt() != null); - } - if (io.airbyte.api.model.generated.OperatorType.WEBHOOK.equals(operatorConfiguration.getOperatorType())) { - Preconditions.checkArgument(operatorConfiguration.getWebhook() != null); - } - } - - public OperationRead updateOperation(final OperationUpdate operationUpdate) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSyncOperation standardSyncOperation = configRepository.getStandardSyncOperation(operationUpdate.getOperationId()); - return persistOperation(updateOperation(operationUpdate, standardSyncOperation)); - } - - private OperationRead persistOperation(final StandardSyncOperation standardSyncOperation) - throws ConfigNotFoundException, IOException, JsonValidationException { - configRepository.writeStandardSyncOperation(standardSyncOperation); - return buildOperationRead(standardSyncOperation.getOperationId()); - } - - public static StandardSyncOperation updateOperation(final OperationUpdate operationUpdate, final StandardSyncOperation standardSyncOperation) { - standardSyncOperation - .withName(operationUpdate.getName()); - OperationsConverter.populateOperatorConfigFromApi(operationUpdate.getOperatorConfiguration(), standardSyncOperation); - return standardSyncOperation; - } - - public OperationReadList listOperationsForConnection(final ConnectionIdRequestBody connectionIdRequestBody) - throws JsonValidationException, ConfigNotFoundException, IOException { - final List operationReads = Lists.newArrayList(); - final StandardSync standardSync = configRepository.getStandardSync(connectionIdRequestBody.getConnectionId()); - for (final UUID operationId : standardSync.getOperationIds()) { - final StandardSyncOperation standardSyncOperation = configRepository.getStandardSyncOperation(operationId); - if (standardSyncOperation.getTombstone() != null && standardSyncOperation.getTombstone()) { - continue; - } - operationReads.add(buildOperationRead(standardSyncOperation)); - } - return new OperationReadList().operations(operationReads); - } - - public OperationRead getOperation(final OperationIdRequestBody operationIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - return buildOperationRead(operationIdRequestBody.getOperationId()); - } - - public void deleteOperationsForConnection(final ConnectionIdRequestBody connectionIdRequestBody) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSync standardSync = configRepository.getStandardSync(connectionIdRequestBody.getConnectionId()); - deleteOperationsForConnection(standardSync, standardSync.getOperationIds()); - } - - public void deleteOperationsForConnection(final UUID connectionId, final List deleteOperationIds) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSync standardSync = configRepository.getStandardSync(connectionId); - deleteOperationsForConnection(standardSync, deleteOperationIds); - } - - public void deleteOperationsForConnection(final StandardSync standardSync, final List deleteOperationIds) - throws JsonValidationException, ConfigNotFoundException, IOException { - final List operationIds = new ArrayList<>(standardSync.getOperationIds()); - for (final UUID operationId : deleteOperationIds) { - operationIds.remove(operationId); - boolean sharedOperation = false; - for (final StandardSync sync : configRepository.listStandardSyncsUsingOperation(operationId)) { - // Check if other connections are using the same operation - if (!sync.getConnectionId().equals(standardSync.getConnectionId())) { - sharedOperation = true; - break; - } - } - if (!sharedOperation) { - removeOperation(operationId); - } - } - - configRepository.updateConnectionOperationIds(standardSync.getConnectionId(), new HashSet<>(operationIds)); - } - - public void deleteOperation(final OperationIdRequestBody operationIdRequestBody) - throws IOException { - final UUID operationId = operationIdRequestBody.getOperationId(); - configRepository.deleteStandardSyncOperation(operationId); - } - - private void removeOperation(final UUID operationId) throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSyncOperation standardSyncOperation = configRepository.getStandardSyncOperation(operationId); - if (standardSyncOperation != null) { - standardSyncOperation.withTombstone(true); - persistOperation(standardSyncOperation); - } else { - throw new ConfigNotFoundException(ConfigSchema.STANDARD_SYNC_OPERATION, operationId.toString()); - } - } - - private OperationRead buildOperationRead(final UUID operationId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSyncOperation standardSyncOperation = configRepository.getStandardSyncOperation(operationId); - if (standardSyncOperation != null) { - return buildOperationRead(standardSyncOperation); - } else { - throw new ConfigNotFoundException(ConfigSchema.STANDARD_SYNC_OPERATION, operationId.toString()); - } - } - - private static OperationRead buildOperationRead(final StandardSyncOperation standardSyncOperation) { - return OperationsConverter.operationReadFromPersistedOperation(standardSyncOperation); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SchedulerHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SchedulerHandler.java deleted file mode 100644 index baf39694a53b7..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SchedulerHandler.java +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableSet; -import com.google.common.hash.HashFunction; -import com.google.common.hash.Hashing; -import io.airbyte.api.model.generated.AdvancedAuth; -import io.airbyte.api.model.generated.AuthSpecification; -import io.airbyte.api.model.generated.CatalogDiff; -import io.airbyte.api.model.generated.CheckConnectionRead; -import io.airbyte.api.model.generated.CheckConnectionRead.StatusEnum; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; -import io.airbyte.api.model.generated.ConnectionStatus; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.DestinationCoreConfig; -import io.airbyte.api.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.DestinationDefinitionSpecificationRead; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationSyncMode; -import io.airbyte.api.model.generated.DestinationUpdate; -import io.airbyte.api.model.generated.FieldTransform; -import io.airbyte.api.model.generated.JobConfigType; -import io.airbyte.api.model.generated.JobIdRequestBody; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.LogRead; -import io.airbyte.api.model.generated.NonBreakingChangesPreference; -import io.airbyte.api.model.generated.SourceCoreConfig; -import io.airbyte.api.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.SourceDefinitionSpecificationRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRequestBody; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceUpdate; -import io.airbyte.api.model.generated.StreamTransform; -import io.airbyte.api.model.generated.StreamTransform.TransformTypeEnum; -import io.airbyte.api.model.generated.SynchronousJobRead; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.ConfigurationUpdate; -import io.airbyte.commons.server.converters.JobConverter; -import io.airbyte.commons.server.converters.OauthModelConverter; -import io.airbyte.commons.server.errors.ValueConflictKnownException; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.commons.server.scheduler.SynchronousJobMetadata; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.temporal.ErrorCode; -import io.airbyte.commons.temporal.TemporalClient.ManualOperationResult; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorCatalog; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardCheckConnectionOutput; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.WebUrlHelper; -import io.airbyte.persistence.job.models.Job; -import io.airbyte.protocol.models.AirbyteCatalog; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Optional; -import java.util.UUID; -import javax.validation.constraints.NotNull; -import lombok.extern.slf4j.Slf4j; - -@Singleton -@Slf4j -public class SchedulerHandler { - - private static final HashFunction HASH_FUNCTION = Hashing.md5(); - - private static final ImmutableSet VALUE_CONFLICT_EXCEPTION_ERROR_CODE_SET = - ImmutableSet.of(ErrorCode.WORKFLOW_DELETED, ErrorCode.WORKFLOW_RUNNING); - - private final ConnectionsHandler connectionsHandler; - private final ConfigRepository configRepository; - private final SecretsRepositoryWriter secretsRepositoryWriter; - private final SynchronousSchedulerClient synchronousSchedulerClient; - private final ConfigurationUpdate configurationUpdate; - private final JsonSchemaValidator jsonSchemaValidator; - private final JobPersistence jobPersistence; - private final JobConverter jobConverter; - private final EventRunner eventRunner; - private final FeatureFlags envVariableFeatureFlags; - private final WebUrlHelper webUrlHelper; - - // TODO: Convert to be fully using micronaut - public SchedulerHandler(final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final SynchronousSchedulerClient synchronousSchedulerClient, - final JobPersistence jobPersistence, - final WorkerEnvironment workerEnvironment, - final LogConfigs logConfigs, - final EventRunner eventRunner, - final ConnectionsHandler connectionsHandler, - final FeatureFlags envVariableFeatureFlags, - final WebUrlHelper webUrlHelper) { - this( - configRepository, - secretsRepositoryWriter, - synchronousSchedulerClient, - new ConfigurationUpdate(configRepository, secretsRepositoryReader), - new JsonSchemaValidator(), - jobPersistence, - eventRunner, - new JobConverter(workerEnvironment, logConfigs), - connectionsHandler, - envVariableFeatureFlags, - webUrlHelper); - } - - @VisibleForTesting - SchedulerHandler(final ConfigRepository configRepository, - final SecretsRepositoryWriter secretsRepositoryWriter, - final SynchronousSchedulerClient synchronousSchedulerClient, - final ConfigurationUpdate configurationUpdate, - final JsonSchemaValidator jsonSchemaValidator, - final JobPersistence jobPersistence, - final EventRunner eventRunner, - final JobConverter jobConverter, - final ConnectionsHandler connectionsHandler, - final FeatureFlags envVariableFeatureFlags, - final WebUrlHelper webUrlHelper) { - this.configRepository = configRepository; - this.secretsRepositoryWriter = secretsRepositoryWriter; - this.synchronousSchedulerClient = synchronousSchedulerClient; - this.configurationUpdate = configurationUpdate; - this.jsonSchemaValidator = jsonSchemaValidator; - this.jobPersistence = jobPersistence; - this.eventRunner = eventRunner; - this.jobConverter = jobConverter; - this.connectionsHandler = connectionsHandler; - this.envVariableFeatureFlags = envVariableFeatureFlags; - this.webUrlHelper = webUrlHelper; - } - - public CheckConnectionRead checkSourceConnectionFromSourceId(final SourceIdRequestBody sourceIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - final SourceConnection source = configRepository.getSourceConnection(sourceIdRequestBody.getSourceId()); - final StandardSourceDefinition sourceDef = configRepository.getStandardSourceDefinition(source.getSourceDefinitionId()); - final String imageName = sourceDef.getDockerRepository() + ":" + sourceDef.getDockerImageTag(); - final boolean isCustomConnector = sourceDef.getCustom(); - final Version protocolVersion = new Version(sourceDef.getProtocolVersion()); - - return reportConnectionStatus(synchronousSchedulerClient.createSourceCheckConnectionJob(source, imageName, protocolVersion, isCustomConnector)); - } - - public CheckConnectionRead checkSourceConnectionFromSourceCreate(final SourceCoreConfig sourceConfig) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSourceDefinition sourceDef = configRepository.getStandardSourceDefinition(sourceConfig.getSourceDefinitionId()); - final var partialConfig = secretsRepositoryWriter.statefulSplitEphemeralSecrets( - sourceConfig.getConnectionConfiguration(), - sourceDef.getSpec()); - - // todo (cgardens) - narrow the struct passed to the client. we are not setting fields that are - // technically declared as required. - final SourceConnection source = new SourceConnection() - .withSourceId(sourceConfig.getSourceId()) - .withSourceDefinitionId(sourceConfig.getSourceDefinitionId()) - .withConfiguration(partialConfig) - .withWorkspaceId(sourceConfig.getWorkspaceId()); - - final Version protocolVersion = new Version(sourceDef.getProtocolVersion()); - - final String imageName = sourceDef.getDockerRepository() + ":" + sourceDef.getDockerImageTag(); - final boolean isCustomConnector = sourceDef.getCustom(); - return reportConnectionStatus(synchronousSchedulerClient.createSourceCheckConnectionJob(source, imageName, protocolVersion, isCustomConnector)); - } - - public CheckConnectionRead checkSourceConnectionFromSourceIdForUpdate(final SourceUpdate sourceUpdate) - throws ConfigNotFoundException, IOException, JsonValidationException { - final SourceConnection updatedSource = - configurationUpdate.source(sourceUpdate.getSourceId(), sourceUpdate.getName(), sourceUpdate.getConnectionConfiguration()); - - final ConnectorSpecification spec = getSpecFromSourceDefinitionId(updatedSource.getSourceDefinitionId()); - jsonSchemaValidator.ensure(spec.getConnectionSpecification(), updatedSource.getConfiguration()); - - final SourceCoreConfig sourceCoreConfig = new SourceCoreConfig() - .sourceId(updatedSource.getSourceId()) - .connectionConfiguration(updatedSource.getConfiguration()) - .sourceDefinitionId(updatedSource.getSourceDefinitionId()) - .workspaceId(updatedSource.getWorkspaceId()); - - return checkSourceConnectionFromSourceCreate(sourceCoreConfig); - } - - public CheckConnectionRead checkDestinationConnectionFromDestinationId(final DestinationIdRequestBody destinationIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - final DestinationConnection destination = configRepository.getDestinationConnection(destinationIdRequestBody.getDestinationId()); - final StandardDestinationDefinition destinationDef = configRepository.getStandardDestinationDefinition(destination.getDestinationDefinitionId()); - final String imageName = destinationDef.getDockerRepository() + ":" + destinationDef.getDockerImageTag(); - final boolean isCustomConnector = destinationDef.getCustom(); - final Version protocolVersion = new Version(destinationDef.getProtocolVersion()); - return reportConnectionStatus( - synchronousSchedulerClient.createDestinationCheckConnectionJob(destination, imageName, protocolVersion, isCustomConnector)); - } - - public CheckConnectionRead checkDestinationConnectionFromDestinationCreate(final DestinationCoreConfig destinationConfig) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardDestinationDefinition destDef = configRepository.getStandardDestinationDefinition(destinationConfig.getDestinationDefinitionId()); - final var partialConfig = secretsRepositoryWriter.statefulSplitEphemeralSecrets( - destinationConfig.getConnectionConfiguration(), - destDef.getSpec()); - final boolean isCustomConnector = destDef.getCustom(); - - // todo (cgardens) - narrow the struct passed to the client. we are not setting fields that are - // technically declared as required. - final DestinationConnection destination = new DestinationConnection() - .withDestinationId(destinationConfig.getDestinationId()) - .withDestinationDefinitionId(destinationConfig.getDestinationDefinitionId()) - .withConfiguration(partialConfig) - .withWorkspaceId(destinationConfig.getWorkspaceId()); - final String imageName = destDef.getDockerRepository() + ":" + destDef.getDockerImageTag(); - final Version protocolVersion = new Version(destDef.getProtocolVersion()); - return reportConnectionStatus( - synchronousSchedulerClient.createDestinationCheckConnectionJob(destination, imageName, protocolVersion, isCustomConnector)); - } - - public CheckConnectionRead checkDestinationConnectionFromDestinationIdForUpdate(final DestinationUpdate destinationUpdate) - throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationConnection updatedDestination = configurationUpdate - .destination(destinationUpdate.getDestinationId(), destinationUpdate.getName(), destinationUpdate.getConnectionConfiguration()); - - final ConnectorSpecification spec = getSpecFromDestinationDefinitionId(updatedDestination.getDestinationDefinitionId()); - jsonSchemaValidator.ensure(spec.getConnectionSpecification(), updatedDestination.getConfiguration()); - - final DestinationCoreConfig destinationCoreConfig = new DestinationCoreConfig() - .destinationId(updatedDestination.getDestinationId()) - .connectionConfiguration(updatedDestination.getConfiguration()) - .destinationDefinitionId(updatedDestination.getDestinationDefinitionId()) - .workspaceId(updatedDestination.getWorkspaceId()); - - return checkDestinationConnectionFromDestinationCreate(destinationCoreConfig); - } - - public SourceDiscoverSchemaRead discoverSchemaForSourceFromSourceId(final SourceDiscoverSchemaRequestBody discoverSchemaRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - final SourceConnection source = configRepository.getSourceConnection(discoverSchemaRequestBody.getSourceId()); - final StandardSourceDefinition sourceDef = configRepository.getStandardSourceDefinition(source.getSourceDefinitionId()); - final String imageName = sourceDef.getDockerRepository() + ":" + sourceDef.getDockerImageTag(); - final boolean isCustomConnector = sourceDef.getCustom(); - - final String configHash = HASH_FUNCTION.hashBytes(Jsons.serialize(source.getConfiguration()).getBytes( - Charsets.UTF_8)).toString(); - final String connectorVersion = sourceDef.getDockerImageTag(); - final Optional currentCatalog = - configRepository.getActorCatalog(discoverSchemaRequestBody.getSourceId(), connectorVersion, configHash); - final boolean bustActorCatalogCache = discoverSchemaRequestBody.getDisableCache() != null && discoverSchemaRequestBody.getDisableCache(); - if (currentCatalog.isEmpty() || bustActorCatalogCache) { - final SynchronousResponse persistedCatalogId = - synchronousSchedulerClient.createDiscoverSchemaJob( - source, - imageName, - connectorVersion, - new Version(sourceDef.getProtocolVersion()), - isCustomConnector); - final SourceDiscoverSchemaRead discoveredSchema = retrieveDiscoveredSchema(persistedCatalogId, sourceDef); - - if (persistedCatalogId.isSuccess() && discoverSchemaRequestBody.getConnectionId() != null) { - // modify discoveredSchema object to add CatalogDiff, containsBreakingChange, and connectionStatus - generateCatalogDiffsAndDisableConnectionsIfNeeded(discoveredSchema, discoverSchemaRequestBody, source.getWorkspaceId()); - } - - return discoveredSchema; - } - final AirbyteCatalog airbyteCatalog = Jsons.object(currentCatalog.get().getCatalog(), AirbyteCatalog.class); - final SynchronousJobRead emptyJob = new SynchronousJobRead() - .configId("NoConfiguration") - .configType(JobConfigType.DISCOVER_SCHEMA) - .id(UUID.randomUUID()) - .createdAt(0L) - .endedAt(0L) - .logs(new LogRead().logLines(new ArrayList<>())) - .succeeded(true); - return new SourceDiscoverSchemaRead() - .catalog(CatalogConverter.toApi(airbyteCatalog, sourceDef)) - .jobInfo(emptyJob) - .catalogId(currentCatalog.get().getId()); - } - - public SourceDiscoverSchemaRead discoverSchemaForSourceFromSourceCreate(final SourceCoreConfig sourceCreate) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSourceDefinition sourceDef = configRepository.getStandardSourceDefinition(sourceCreate.getSourceDefinitionId()); - final var partialConfig = secretsRepositoryWriter.statefulSplitEphemeralSecrets( - sourceCreate.getConnectionConfiguration(), - sourceDef.getSpec()); - - final String imageName = sourceDef.getDockerRepository() + ":" + sourceDef.getDockerImageTag(); - final boolean isCustomConnector = sourceDef.getCustom(); - // todo (cgardens) - narrow the struct passed to the client. we are not setting fields that are - // technically declared as required. - final SourceConnection source = new SourceConnection() - .withSourceDefinitionId(sourceCreate.getSourceDefinitionId()) - .withConfiguration(partialConfig) - .withWorkspaceId(sourceCreate.getWorkspaceId()); - final SynchronousResponse response = synchronousSchedulerClient.createDiscoverSchemaJob( - source, - imageName, - sourceDef.getDockerImageTag(), - new Version( - sourceDef.getProtocolVersion()), - isCustomConnector); - return retrieveDiscoveredSchema(response, sourceDef); - } - - private SourceDiscoverSchemaRead retrieveDiscoveredSchema(final SynchronousResponse response, final StandardSourceDefinition sourceDef) - throws ConfigNotFoundException, IOException { - final SourceDiscoverSchemaRead sourceDiscoverSchemaRead = new SourceDiscoverSchemaRead() - .jobInfo(jobConverter.getSynchronousJobRead(response)); - - if (response.isSuccess()) { - final ActorCatalog catalog = configRepository.getActorCatalogById(response.getOutput()); - final AirbyteCatalog persistenceCatalog = Jsons.object(catalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - sourceDiscoverSchemaRead.catalog(CatalogConverter.toApi(persistenceCatalog, sourceDef)); - sourceDiscoverSchemaRead.catalogId(response.getOutput()); - } - - return sourceDiscoverSchemaRead; - } - - public SourceDefinitionSpecificationRead getSourceDefinitionSpecification(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final UUID sourceDefinitionId = sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId(); - final StandardSourceDefinition source = configRepository.getStandardSourceDefinition(sourceDefinitionId); - final ConnectorSpecification spec = source.getSpec(); - - final SourceDefinitionSpecificationRead specRead = new SourceDefinitionSpecificationRead() - .jobInfo(jobConverter.getSynchronousJobRead(SynchronousJobMetadata.mock(ConfigType.GET_SPEC))) - .connectionSpecification(spec.getConnectionSpecification()) - .sourceDefinitionId(sourceDefinitionId); - - if (spec.getDocumentationUrl() != null) { - specRead.documentationUrl(spec.getDocumentationUrl().toString()); - } - - final Optional authSpec = OauthModelConverter.getAuthSpec(spec); - authSpec.ifPresent(specRead::setAuthSpecification); - - final Optional advancedAuth = OauthModelConverter.getAdvancedAuth(spec); - advancedAuth.ifPresent(specRead::setAdvancedAuth); - - return specRead; - } - - public DestinationDefinitionSpecificationRead getDestinationSpecification( - final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final UUID destinationDefinitionId = destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId(); - final StandardDestinationDefinition destination = configRepository.getStandardDestinationDefinition(destinationDefinitionId); - final ConnectorSpecification spec = destination.getSpec(); - - final DestinationDefinitionSpecificationRead specRead = new DestinationDefinitionSpecificationRead() - .jobInfo(jobConverter.getSynchronousJobRead(SynchronousJobMetadata.mock(ConfigType.GET_SPEC))) - .supportedDestinationSyncModes(Enums.convertListTo(spec.getSupportedDestinationSyncModes(), DestinationSyncMode.class)) - .connectionSpecification(spec.getConnectionSpecification()) - .documentationUrl(spec.getDocumentationUrl().toString()) - .destinationDefinitionId(destinationDefinitionId); - - final Optional authSpec = OauthModelConverter.getAuthSpec(spec); - authSpec.ifPresent(specRead::setAuthSpecification); - - final Optional advancedAuth = OauthModelConverter.getAdvancedAuth(spec); - advancedAuth.ifPresent(specRead::setAdvancedAuth); - - return specRead; - } - - public JobInfoRead syncConnection(final ConnectionIdRequestBody connectionIdRequestBody) - throws IOException, JsonValidationException, ConfigNotFoundException { - return submitManualSyncToWorker(connectionIdRequestBody.getConnectionId()); - } - - public JobInfoRead resetConnection(final ConnectionIdRequestBody connectionIdRequestBody) - throws IOException, JsonValidationException, ConfigNotFoundException { - return submitResetConnectionToWorker(connectionIdRequestBody.getConnectionId()); - } - - public JobInfoRead cancelJob(final JobIdRequestBody jobIdRequestBody) throws IOException { - return submitCancellationToWorker(jobIdRequestBody.getId()); - } - - // Find all connections that use the source from the SourceDiscoverSchemaRequestBody. For each one, - // determine whether 1. the source schema change resulted in a broken connection or 2. the user - // wants the connection disabled when non-breaking changes are detected. If so, disable that - // connection. Modify the current discoveredSchema object to add a CatalogDiff, - // containsBreakingChange parameter, and connectionStatus parameter. - private void generateCatalogDiffsAndDisableConnectionsIfNeeded(final SourceDiscoverSchemaRead discoveredSchema, - final SourceDiscoverSchemaRequestBody discoverSchemaRequestBody, - final UUID workspaceId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final ConnectionReadList connectionsForSource = connectionsHandler.listConnectionsForSource(discoverSchemaRequestBody.getSourceId(), false); - for (final ConnectionRead connectionRead : connectionsForSource.getConnections()) { - final Optional catalogUsedToMakeConfiguredCatalog = connectionsHandler - .getConnectionAirbyteCatalog(connectionRead.getConnectionId()); - final io.airbyte.api.model.generated.@NotNull AirbyteCatalog currentAirbyteCatalog = - connectionRead.getSyncCatalog(); - final CatalogDiff diff = - connectionsHandler.getDiff(catalogUsedToMakeConfiguredCatalog.orElse(currentAirbyteCatalog), discoveredSchema.getCatalog(), - CatalogConverter.toConfiguredProtocol(currentAirbyteCatalog)); - final boolean containsBreakingChange = containsBreakingChange(diff); - final ConnectionUpdate updateObject = - new ConnectionUpdate().breakingChange(containsBreakingChange).connectionId(connectionRead.getConnectionId()); - final ConnectionStatus connectionStatus; - if (shouldDisableConnection(containsBreakingChange, connectionRead.getNonBreakingChangesPreference(), diff)) { - connectionStatus = ConnectionStatus.INACTIVE; - } else { - connectionStatus = connectionRead.getStatus(); - } - updateObject.status(connectionStatus); - connectionsHandler.updateConnection(updateObject); - if (shouldNotifySchemaChange(diff, connectionRead, discoverSchemaRequestBody)) { - final String url = webUrlHelper.getConnectionUrl(workspaceId, connectionRead.getConnectionId()); - eventRunner.sendSchemaChangeNotification(connectionRead.getConnectionId(), url); - } - if (connectionRead.getConnectionId().equals(discoverSchemaRequestBody.getConnectionId())) { - discoveredSchema.catalogDiff(diff).breakingChange(containsBreakingChange).connectionStatus(connectionStatus); - } - } - } - - private boolean shouldNotifySchemaChange(final CatalogDiff diff, - final ConnectionRead connectionRead, - final SourceDiscoverSchemaRequestBody requestBody) { - return !diff.getTransforms().isEmpty() && connectionRead.getNotifySchemaChanges() && requestBody.getNotifySchemaChange() != null - && requestBody.getNotifySchemaChange(); - } - - private boolean shouldDisableConnection(final boolean containsBreakingChange, - final NonBreakingChangesPreference preference, - final CatalogDiff diff) { - if (!envVariableFeatureFlags.autoDetectSchema()) { - return false; - } - - return containsBreakingChange || (preference == NonBreakingChangesPreference.DISABLE && !diff.getTransforms().isEmpty()); - } - - private CheckConnectionRead reportConnectionStatus(final SynchronousResponse response) { - final CheckConnectionRead checkConnectionRead = new CheckConnectionRead() - .jobInfo(jobConverter.getSynchronousJobRead(response)); - - if (response.getOutput() != null) { - checkConnectionRead - .status(Enums.convertTo(response.getOutput().getStatus(), StatusEnum.class)) - .message(response.getOutput().getMessage()); - } else { - checkConnectionRead - .status(StatusEnum.FAILED) - .message("Check Connection Failed!"); - } - - return checkConnectionRead; - } - - private ConnectorSpecification getSpecFromSourceDefinitionId(final UUID sourceDefId) - throws IOException, JsonValidationException, ConfigNotFoundException { - final StandardSourceDefinition sourceDef = configRepository.getStandardSourceDefinition(sourceDefId); - return sourceDef.getSpec(); - } - - private ConnectorSpecification getSpecFromDestinationDefinitionId(final UUID destDefId) - throws IOException, JsonValidationException, ConfigNotFoundException { - final StandardDestinationDefinition destinationDef = configRepository.getStandardDestinationDefinition(destDefId); - return destinationDef.getSpec(); - } - - private JobInfoRead submitCancellationToWorker(final Long jobId) throws IOException { - final Job job = jobPersistence.getJob(jobId); - - final ManualOperationResult cancellationResult = eventRunner.startNewCancellation(UUID.fromString(job.getScope())); - if (cancellationResult.getFailingReason().isPresent()) { - throw new IllegalStateException(cancellationResult.getFailingReason().get()); - } - - // query same job ID again to get updated job info after cancellation - return jobConverter.getJobInfoRead(jobPersistence.getJob(jobId)); - } - - private JobInfoRead submitManualSyncToWorker(final UUID connectionId) - throws IOException, IllegalStateException, JsonValidationException, ConfigNotFoundException { - // get standard sync to validate connection id before submitting sync to temporal - configRepository.getStandardSync(connectionId); - final ManualOperationResult manualSyncResult = eventRunner.startNewManualSync(connectionId); - - return readJobFromResult(manualSyncResult); - } - - private JobInfoRead submitResetConnectionToWorker(final UUID connectionId) throws IOException, IllegalStateException, ConfigNotFoundException { - final ManualOperationResult resetConnectionResult = eventRunner.resetConnection( - connectionId, - configRepository.getAllStreamsForConnection(connectionId), - false); - - return readJobFromResult(resetConnectionResult); - } - - private JobInfoRead readJobFromResult(final ManualOperationResult manualOperationResult) throws IOException, IllegalStateException { - if (manualOperationResult.getFailingReason().isPresent()) { - if (VALUE_CONFLICT_EXCEPTION_ERROR_CODE_SET.contains(manualOperationResult.getErrorCode().get())) { - throw new ValueConflictKnownException(manualOperationResult.getFailingReason().get()); - } else { - throw new IllegalStateException(manualOperationResult.getFailingReason().get()); - } - } - - final Job job = jobPersistence.getJob(manualOperationResult.getJobId().get()); - - return jobConverter.getJobInfoRead(job); - } - - private boolean containsBreakingChange(final CatalogDiff diff) { - for (final StreamTransform streamTransform : diff.getTransforms()) { - if (streamTransform.getTransformType() != TransformTypeEnum.UPDATE_STREAM) { - continue; - } - - final boolean anyBreakingFieldTransforms = streamTransform.getUpdateStream().stream().anyMatch(FieldTransform::getBreaking); - if (anyBreakingFieldTransforms) { - return true; - } - } - - return false; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandler.java deleted file mode 100644 index c2ad9aa4189cc..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandler.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.api.model.generated.CustomSourceDefinitionCreate; -import io.airbyte.api.model.generated.PrivateSourceDefinitionRead; -import io.airbyte.api.model.generated.PrivateSourceDefinitionReadList; -import io.airbyte.api.model.generated.ReleaseStage; -import io.airbyte.api.model.generated.SourceDefinitionCreate; -import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.SourceDefinitionRead; -import io.airbyte.api.model.generated.SourceDefinitionRead.SourceTypeEnum; -import io.airbyte.api.model.generated.SourceDefinitionReadList; -import io.airbyte.api.model.generated.SourceDefinitionUpdate; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.commons.server.ServerConstants; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.server.converters.SpecFetcher; -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.commons.server.errors.InternalServerKnownException; -import io.airbyte.commons.server.errors.UnsupportedProtocolVersionException; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.commons.util.MoreLists; -import io.airbyte.commons.version.AirbyteProtocolVersion; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorDefinitionResourceRequirements; -import io.airbyte.config.ActorType; -import io.airbyte.config.Configs; -import io.airbyte.config.EnvConfigs; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.time.LocalDate; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -@SuppressWarnings("PMD.AvoidCatchingNPE") -@Singleton -public class SourceDefinitionsHandler { - - private final ConfigRepository configRepository; - private final Supplier uuidSupplier; - private final AirbyteGithubStore githubStore; - private final SynchronousSchedulerClient schedulerSynchronousClient; - private final SourceHandler sourceHandler; - private final AirbyteProtocolVersionRange protocolVersionRange; - - @Inject - public SourceDefinitionsHandler(final ConfigRepository configRepository, - final Supplier uuidSupplier, - final SynchronousSchedulerClient schedulerSynchronousClient, - final AirbyteGithubStore githubStore, - final SourceHandler sourceHandler, - final AirbyteProtocolVersionRange protocolVersionRange) { - this.configRepository = configRepository; - this.uuidSupplier = uuidSupplier; - this.schedulerSynchronousClient = schedulerSynchronousClient; - this.githubStore = githubStore; - this.sourceHandler = sourceHandler; - this.protocolVersionRange = protocolVersionRange; - } - - // This should be deleted when cloud is migrated to micronaut - @Deprecated(forRemoval = true) - public SourceDefinitionsHandler(final ConfigRepository configRepository, - final SynchronousSchedulerClient schedulerSynchronousClient, - final SourceHandler sourceHandler) { - this.configRepository = configRepository; - this.uuidSupplier = UUID::randomUUID; - this.schedulerSynchronousClient = schedulerSynchronousClient; - this.githubStore = AirbyteGithubStore.production(); - this.sourceHandler = sourceHandler; - final Configs configs = new EnvConfigs(); - this.protocolVersionRange = new AirbyteProtocolVersionRange(configs.getAirbyteProtocolVersionMin(), configs.getAirbyteProtocolVersionMax()); - } - - @VisibleForTesting - static SourceDefinitionRead buildSourceDefinitionRead(final StandardSourceDefinition standardSourceDefinition) { - try { - return new SourceDefinitionRead() - .sourceDefinitionId(standardSourceDefinition.getSourceDefinitionId()) - .name(standardSourceDefinition.getName()) - .sourceType(getSourceType(standardSourceDefinition)) - .dockerRepository(standardSourceDefinition.getDockerRepository()) - .dockerImageTag(standardSourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(standardSourceDefinition.getDocumentationUrl())) - .icon(loadIcon(standardSourceDefinition.getIcon())) - .protocolVersion(standardSourceDefinition.getProtocolVersion()) - .releaseStage(getReleaseStage(standardSourceDefinition)) - .releaseDate(getReleaseDate(standardSourceDefinition)) - .resourceRequirements(ApiPojoConverters.actorDefResourceReqsToApi(standardSourceDefinition.getResourceRequirements())); - - } catch (final URISyntaxException | NullPointerException e) { - throw new InternalServerKnownException("Unable to process retrieved latest source definitions list", e); - } - } - - private static SourceTypeEnum getSourceType(final StandardSourceDefinition standardSourceDefinition) { - if (standardSourceDefinition.getSourceType() == null) { - return null; - } - return SourceTypeEnum.fromValue(standardSourceDefinition.getSourceType().value()); - } - - private static ReleaseStage getReleaseStage(final StandardSourceDefinition standardSourceDefinition) { - if (standardSourceDefinition.getReleaseStage() == null) { - return null; - } - return ReleaseStage.fromValue(standardSourceDefinition.getReleaseStage().value()); - } - - private static LocalDate getReleaseDate(final StandardSourceDefinition standardSourceDefinition) { - if (standardSourceDefinition.getReleaseDate() == null || standardSourceDefinition.getReleaseDate().isBlank()) { - return null; - } - - return LocalDate.parse(standardSourceDefinition.getReleaseDate()); - } - - public SourceDefinitionReadList listSourceDefinitions() throws IOException, JsonValidationException { - return toSourceDefinitionReadList(configRepository.listStandardSourceDefinitions(false)); - } - - private static SourceDefinitionReadList toSourceDefinitionReadList(final List defs) { - final List reads = defs.stream() - .map(SourceDefinitionsHandler::buildSourceDefinitionRead) - .collect(Collectors.toList()); - return new SourceDefinitionReadList().sourceDefinitions(reads); - } - - public SourceDefinitionReadList listLatestSourceDefinitions() { - return toSourceDefinitionReadList(getLatestSources()); - } - - private List getLatestSources() { - try { - return githubStore.getLatestSources(); - } catch (final InterruptedException e) { - throw new InternalServerKnownException("Request to retrieve latest destination definitions failed", e); - } - } - - public SourceDefinitionReadList listSourceDefinitionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws IOException { - return toSourceDefinitionReadList(MoreLists.concat( - configRepository.listPublicSourceDefinitions(false), - configRepository.listGrantedSourceDefinitions(workspaceIdRequestBody.getWorkspaceId(), false))); - } - - public PrivateSourceDefinitionReadList listPrivateSourceDefinitions(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws IOException { - final List> standardSourceDefinitionBooleanMap = - configRepository.listGrantableSourceDefinitions(workspaceIdRequestBody.getWorkspaceId(), false); - return toPrivateSourceDefinitionReadList(standardSourceDefinitionBooleanMap); - } - - private static PrivateSourceDefinitionReadList toPrivateSourceDefinitionReadList(final List> defs) { - final List reads = defs.stream() - .map(entry -> new PrivateSourceDefinitionRead() - .sourceDefinition(buildSourceDefinitionRead(entry.getKey())) - .granted(entry.getValue())) - .collect(Collectors.toList()); - return new PrivateSourceDefinitionReadList().sourceDefinitions(reads); - } - - public SourceDefinitionRead getSourceDefinition(final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - return buildSourceDefinitionRead(configRepository.getStandardSourceDefinition(sourceDefinitionIdRequestBody.getSourceDefinitionId())); - } - - public SourceDefinitionRead getSourceDefinitionForWorkspace(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final UUID definitionId = sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId(); - final UUID workspaceId = sourceDefinitionIdWithWorkspaceId.getWorkspaceId(); - if (!configRepository.workspaceCanUseDefinition(definitionId, workspaceId)) { - throw new IdNotFoundKnownException("Cannot find the requested definition with given id for this workspace", definitionId.toString()); - } - return getSourceDefinition(new SourceDefinitionIdRequestBody().sourceDefinitionId(definitionId)); - } - - public SourceDefinitionRead createCustomSourceDefinition(final CustomSourceDefinitionCreate customSourceDefinitionCreate) - throws IOException { - final StandardSourceDefinition sourceDefinition = sourceDefinitionFromCreate(customSourceDefinitionCreate.getSourceDefinition()) - .withPublic(false) - .withCustom(true); - if (!protocolVersionRange.isSupported(new Version(sourceDefinition.getProtocolVersion()))) { - throw new UnsupportedProtocolVersionException(sourceDefinition.getProtocolVersion(), protocolVersionRange.min(), protocolVersionRange.max()); - } - configRepository.writeCustomSourceDefinition(sourceDefinition, customSourceDefinitionCreate.getWorkspaceId()); - - return buildSourceDefinitionRead(sourceDefinition); - } - - private StandardSourceDefinition sourceDefinitionFromCreate(final SourceDefinitionCreate sourceDefinitionCreate) - throws IOException { - final ConnectorSpecification spec = - getSpecForImage( - sourceDefinitionCreate.getDockerRepository(), - sourceDefinitionCreate.getDockerImageTag(), - // Only custom connectors can be created via handlers. - true); - - final Version airbyteProtocolVersion = AirbyteProtocolVersion.getWithDefault(spec.getProtocolVersion()); - - final UUID id = uuidSupplier.get(); - return new StandardSourceDefinition() - .withSourceDefinitionId(id) - .withDockerRepository(sourceDefinitionCreate.getDockerRepository()) - .withDockerImageTag(sourceDefinitionCreate.getDockerImageTag()) - .withDocumentationUrl(sourceDefinitionCreate.getDocumentationUrl().toString()) - .withName(sourceDefinitionCreate.getName()) - .withIcon(sourceDefinitionCreate.getIcon()) - .withSpec(spec) - .withProtocolVersion(airbyteProtocolVersion.serialize()) - .withTombstone(false) - .withReleaseStage(StandardSourceDefinition.ReleaseStage.CUSTOM) - .withResourceRequirements(ApiPojoConverters.actorDefResourceReqsToInternal(sourceDefinitionCreate.getResourceRequirements())); - } - - public SourceDefinitionRead updateSourceDefinition(final SourceDefinitionUpdate sourceDefinitionUpdate) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSourceDefinition currentSourceDefinition = - configRepository.getStandardSourceDefinition(sourceDefinitionUpdate.getSourceDefinitionId()); - - // specs are re-fetched from the container if the image tag has changed, or if the tag is "dev", - // to allow for easier iteration of dev images - final boolean specNeedsUpdate = !currentSourceDefinition.getDockerImageTag().equals(sourceDefinitionUpdate.getDockerImageTag()) - || ServerConstants.DEV_IMAGE_TAG.equals(sourceDefinitionUpdate.getDockerImageTag()); - final ConnectorSpecification spec = specNeedsUpdate - ? getSpecForImage(currentSourceDefinition.getDockerRepository(), sourceDefinitionUpdate.getDockerImageTag(), - currentSourceDefinition.getCustom()) - : currentSourceDefinition.getSpec(); - final ActorDefinitionResourceRequirements updatedResourceReqs = sourceDefinitionUpdate.getResourceRequirements() != null - ? ApiPojoConverters.actorDefResourceReqsToInternal(sourceDefinitionUpdate.getResourceRequirements()) - : currentSourceDefinition.getResourceRequirements(); - - final Version airbyteProtocolVersion = AirbyteProtocolVersion.getWithDefault(spec.getProtocolVersion()); - if (!protocolVersionRange.isSupported(airbyteProtocolVersion)) { - throw new UnsupportedProtocolVersionException(airbyteProtocolVersion, protocolVersionRange.min(), protocolVersionRange.max()); - } - - final StandardSourceDefinition newSource = new StandardSourceDefinition() - .withSourceDefinitionId(currentSourceDefinition.getSourceDefinitionId()) - .withDockerImageTag(sourceDefinitionUpdate.getDockerImageTag()) - .withDockerRepository(currentSourceDefinition.getDockerRepository()) - .withDocumentationUrl(currentSourceDefinition.getDocumentationUrl()) - .withName(currentSourceDefinition.getName()) - .withIcon(currentSourceDefinition.getIcon()) - .withSpec(spec) - .withProtocolVersion(airbyteProtocolVersion.serialize()) - .withTombstone(currentSourceDefinition.getTombstone()) - .withPublic(currentSourceDefinition.getPublic()) - .withCustom(currentSourceDefinition.getCustom()) - .withReleaseStage(currentSourceDefinition.getReleaseStage()) - .withReleaseDate(currentSourceDefinition.getReleaseDate()) - .withResourceRequirements(updatedResourceReqs); - - configRepository.writeStandardSourceDefinition(newSource); - configRepository.clearUnsupportedProtocolVersionFlag(newSource.getSourceDefinitionId(), ActorType.SOURCE, protocolVersionRange); - - return buildSourceDefinitionRead(newSource); - } - - public void deleteSourceDefinition(final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // "delete" all sources associated with the source definition as well. This will cascade to - // connections that depend on any deleted sources. - // Delete sources first in case a failure occurs mid-operation. - - final StandardSourceDefinition persistedSourceDefinition = - configRepository.getStandardSourceDefinition(sourceDefinitionIdRequestBody.getSourceDefinitionId()); - - for (final SourceRead sourceRead : sourceHandler.listSourcesForSourceDefinition(sourceDefinitionIdRequestBody).getSources()) { - sourceHandler.deleteSource(sourceRead); - } - - persistedSourceDefinition.withTombstone(true); - configRepository.writeStandardSourceDefinition(persistedSourceDefinition); - } - - private ConnectorSpecification getSpecForImage(final String dockerRepository, final String imageTag, final boolean isCustomConnector) - throws IOException { - final String imageName = dockerRepository + ":" + imageTag; - final SynchronousResponse getSpecResponse = schedulerSynchronousClient.createGetSpecJob(imageName, isCustomConnector); - return SpecFetcher.getSpecFromJob(getSpecResponse); - } - - public static String loadIcon(final String name) { - try { - return name == null ? null : MoreResources.readResource("icons/" + name); - } catch (final Exception e) { - return null; - } - } - - public PrivateSourceDefinitionRead grantSourceDefinitionToWorkspace( - final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSourceDefinition standardSourceDefinition = - configRepository.getStandardSourceDefinition(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId()); - configRepository.writeActorDefinitionWorkspaceGrant( - sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId(), - sourceDefinitionIdWithWorkspaceId.getWorkspaceId()); - return new PrivateSourceDefinitionRead() - .sourceDefinition(buildSourceDefinitionRead(standardSourceDefinition)) - .granted(true); - } - - public void revokeSourceDefinitionFromWorkspace(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) - throws IOException { - configRepository.deleteActorDefinitionWorkspaceGrant( - sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId(), - sourceDefinitionIdWithWorkspaceId.getWorkspaceId()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceHandler.java deleted file mode 100644 index 102b4cf2ac8e0..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/SourceHandler.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.ActorCatalogWithUpdatedAt; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.DiscoverCatalogResult; -import io.airbyte.api.model.generated.SourceCloneConfiguration; -import io.airbyte.api.model.generated.SourceCloneRequestBody; -import io.airbyte.api.model.generated.SourceCreate; -import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.model.generated.SourceDiscoverSchemaWriteRequestBody; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceReadList; -import io.airbyte.api.model.generated.SourceSearch; -import io.airbyte.api.model.generated.SourceSnippetRead; -import io.airbyte.api.model.generated.SourceUpdate; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.server.converters.ConfigurationUpdate; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.protocol.models.AirbyteCatalog; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.function.Supplier; - -@Singleton -public class SourceHandler { - - private final Supplier uuidGenerator; - private final ConfigRepository configRepository; - private final SecretsRepositoryReader secretsRepositoryReader; - private final SecretsRepositoryWriter secretsRepositoryWriter; - private final JsonSchemaValidator validator; - private final ConnectionsHandler connectionsHandler; - private final ConfigurationUpdate configurationUpdate; - private final JsonSecretsProcessor secretsProcessor; - private final OAuthConfigSupplier oAuthConfigSupplier; - - @Inject - SourceHandler(final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final JsonSchemaValidator integrationSchemaValidation, - final ConnectionsHandler connectionsHandler, - final Supplier uuidGenerator, - final JsonSecretsProcessor secretsProcessor, - final ConfigurationUpdate configurationUpdate, - final OAuthConfigSupplier oAuthConfigSupplier) { - this.configRepository = configRepository; - this.secretsRepositoryReader = secretsRepositoryReader; - this.secretsRepositoryWriter = secretsRepositoryWriter; - validator = integrationSchemaValidation; - this.connectionsHandler = connectionsHandler; - this.uuidGenerator = uuidGenerator; - this.configurationUpdate = configurationUpdate; - this.secretsProcessor = secretsProcessor; - this.oAuthConfigSupplier = oAuthConfigSupplier; - } - - public SourceHandler(final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final JsonSchemaValidator integrationSchemaValidation, - final ConnectionsHandler connectionsHandler, - final OAuthConfigSupplier oAuthConfigSupplier) { - this( - configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - integrationSchemaValidation, - connectionsHandler, - UUID::randomUUID, - JsonSecretsProcessor.builder() - .copySecrets(true) - .build(), - new ConfigurationUpdate(configRepository, secretsRepositoryReader), - oAuthConfigSupplier); - } - - public SourceRead createSource(final SourceCreate sourceCreate) - throws ConfigNotFoundException, IOException, JsonValidationException { - // validate configuration - final ConnectorSpecification spec = getSpecFromSourceDefinitionId( - sourceCreate.getSourceDefinitionId()); - validateSource(spec, sourceCreate.getConnectionConfiguration()); - - // persist - final UUID sourceId = uuidGenerator.get(); - persistSourceConnection( - sourceCreate.getName() != null ? sourceCreate.getName() : "default", - sourceCreate.getSourceDefinitionId(), - sourceCreate.getWorkspaceId(), - sourceId, - false, - sourceCreate.getConnectionConfiguration(), - spec); - - // read configuration from db - return buildSourceRead(configRepository.getSourceConnection(sourceId), spec); - } - - public SourceRead updateSource(final SourceUpdate sourceUpdate) - throws ConfigNotFoundException, IOException, JsonValidationException { - - final UUID sourceId = sourceUpdate.getSourceId(); - final SourceConnection updatedSource = configurationUpdate - .source(sourceId, sourceUpdate.getName(), - sourceUpdate.getConnectionConfiguration()); - final ConnectorSpecification spec = getSpecFromSourceId(sourceId); - validateSource(spec, sourceUpdate.getConnectionConfiguration()); - - // persist - persistSourceConnection( - updatedSource.getName(), - updatedSource.getSourceDefinitionId(), - updatedSource.getWorkspaceId(), - updatedSource.getSourceId(), - updatedSource.getTombstone(), - updatedSource.getConfiguration(), - spec); - - // read configuration from db - return buildSourceRead(configRepository.getSourceConnection(sourceId), spec); - } - - public SourceRead getSource(final SourceIdRequestBody sourceIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - return buildSourceRead(sourceIdRequestBody.getSourceId()); - } - - public ActorCatalogWithUpdatedAt getMostRecentSourceActorCatalogWithUpdatedAt(final SourceIdRequestBody sourceIdRequestBody) - throws IOException { - Optional actorCatalog = - configRepository.getMostRecentSourceActorCatalog(sourceIdRequestBody.getSourceId()); - if (actorCatalog.isEmpty()) { - return new ActorCatalogWithUpdatedAt(); - } else { - return new ActorCatalogWithUpdatedAt().updatedAt(actorCatalog.get().getUpdatedAt()).catalog(actorCatalog.get().getCatalog()); - } - } - - public SourceRead cloneSource(final SourceCloneRequestBody sourceCloneRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // read source configuration from db - final SourceRead sourceToClone = buildSourceReadWithSecrets(sourceCloneRequestBody.getSourceCloneId()); - final SourceCloneConfiguration sourceCloneConfiguration = sourceCloneRequestBody.getSourceConfiguration(); - - final String copyText = " (Copy)"; - final String sourceName = sourceToClone.getName() + copyText; - - final SourceCreate sourceCreate = new SourceCreate() - .name(sourceName) - .sourceDefinitionId(sourceToClone.getSourceDefinitionId()) - .connectionConfiguration(sourceToClone.getConnectionConfiguration()) - .workspaceId(sourceToClone.getWorkspaceId()); - - if (sourceCloneConfiguration != null) { - if (sourceCloneConfiguration.getName() != null) { - sourceCreate.name(sourceCloneConfiguration.getName()); - } - - if (sourceCloneConfiguration.getConnectionConfiguration() != null) { - sourceCreate.connectionConfiguration(sourceCloneConfiguration.getConnectionConfiguration()); - } - } - - return createSource(sourceCreate); - } - - public SourceReadList listSourcesForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - - final List sourceConnections = configRepository.listWorkspaceSourceConnection(workspaceIdRequestBody.getWorkspaceId()); - - final List reads = Lists.newArrayList(); - for (final SourceConnection sc : sourceConnections) { - reads.add(buildSourceRead(sc)); - } - - return new SourceReadList().sources(reads); - } - - public SourceReadList listSourcesForSourceDefinition(final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - - final List reads = Lists.newArrayList(); - for (final SourceConnection sourceConnection : configRepository.listSourcesForDefinition(sourceDefinitionIdRequestBody.getSourceDefinitionId())) { - reads.add(buildSourceRead(sourceConnection)); - } - - return new SourceReadList().sources(reads); - } - - public SourceReadList searchSources(final SourceSearch sourceSearch) - throws ConfigNotFoundException, IOException, JsonValidationException { - final List reads = Lists.newArrayList(); - - for (final SourceConnection sci : configRepository.listSourceConnection()) { - if (!sci.getTombstone()) { - final SourceRead sourceRead = buildSourceRead(sci); - if (connectionsHandler.matchSearch(sourceSearch, sourceRead)) { - reads.add(sourceRead); - } - } - } - - return new SourceReadList().sources(reads); - } - - public void deleteSource(final SourceIdRequestBody sourceIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // get existing source - final SourceRead source = buildSourceRead(sourceIdRequestBody.getSourceId()); - deleteSource(source); - } - - public void deleteSource(final SourceRead source) - throws JsonValidationException, IOException, ConfigNotFoundException { - // "delete" all connections associated with source as well. - // Delete connections first in case it fails in the middle, source will still be visible - final var workspaceIdRequestBody = new WorkspaceIdRequestBody() - .workspaceId(source.getWorkspaceId()); - - final List uuidsToDelete = connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody) - .getConnections().stream() - .filter(con -> con.getSourceId().equals(source.getSourceId())) - .map(ConnectionRead::getConnectionId) - .toList(); - - for (final UUID uuidToDelete : uuidsToDelete) { - connectionsHandler.deleteConnection(uuidToDelete); - } - - final var spec = getSpecFromSourceId(source.getSourceId()); - final var fullConfig = secretsRepositoryReader.getSourceConnectionWithSecrets(source.getSourceId()).getConfiguration(); - - // persist - persistSourceConnection( - source.getName(), - source.getSourceDefinitionId(), - source.getWorkspaceId(), - source.getSourceId(), - true, - fullConfig, - spec); - } - - public DiscoverCatalogResult writeDiscoverCatalogResult(final SourceDiscoverSchemaWriteRequestBody request) - throws JsonValidationException, IOException { - final AirbyteCatalog persistenceCatalog = CatalogConverter.toProtocol(request.getCatalog()); - UUID catalogId = configRepository.writeActorCatalogFetchEvent( - persistenceCatalog, - request.getSourceId(), - request.getConnectorVersion(), - request.getConfigurationHash()); - return new DiscoverCatalogResult().catalogId(catalogId); - } - - private SourceRead buildSourceRead(final UUID sourceId) - throws ConfigNotFoundException, IOException, JsonValidationException { - // read configuration from db - final SourceConnection sourceConnection = configRepository.getSourceConnection(sourceId); - return buildSourceRead(sourceConnection); - } - - private SourceRead buildSourceRead(final SourceConnection sourceConnection) - throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardSourceDefinition sourceDef = configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId()); - final ConnectorSpecification spec = sourceDef.getSpec(); - return buildSourceRead(sourceConnection, spec); - } - - private SourceRead buildSourceRead(final SourceConnection sourceConnection, final ConnectorSpecification spec) - throws ConfigNotFoundException, IOException, JsonValidationException { - // read configuration from db - final StandardSourceDefinition standardSourceDefinition = configRepository - .getStandardSourceDefinition(sourceConnection.getSourceDefinitionId()); - final JsonNode sanitizedConfig = secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), spec.getConnectionSpecification()); - sourceConnection.setConfiguration(sanitizedConfig); - return toSourceRead(sourceConnection, standardSourceDefinition); - } - - private SourceRead buildSourceReadWithSecrets(final UUID sourceId) - throws ConfigNotFoundException, IOException, JsonValidationException { - // read configuration from db - final SourceConnection sourceConnection = secretsRepositoryReader.getSourceConnectionWithSecrets(sourceId); - final StandardSourceDefinition standardSourceDefinition = configRepository - .getStandardSourceDefinition(sourceConnection.getSourceDefinitionId()); - return toSourceRead(sourceConnection, standardSourceDefinition); - } - - private void validateSource(final ConnectorSpecification spec, final JsonNode implementationJson) - throws JsonValidationException { - validator.ensure(spec.getConnectionSpecification(), implementationJson); - } - - private ConnectorSpecification getSpecFromSourceId(final UUID sourceId) - throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = configRepository.getSourceConnection(sourceId); - return getSpecFromSourceDefinitionId(source.getSourceDefinitionId()); - } - - private ConnectorSpecification getSpecFromSourceDefinitionId(final UUID sourceDefId) - throws IOException, JsonValidationException, ConfigNotFoundException { - final StandardSourceDefinition sourceDef = configRepository.getStandardSourceDefinition(sourceDefId); - return sourceDef.getSpec(); - } - - private void persistSourceConnection(final String name, - final UUID sourceDefinitionId, - final UUID workspaceId, - final UUID sourceId, - final boolean tombstone, - final JsonNode configurationJson, - final ConnectorSpecification spec) - throws JsonValidationException, IOException { - final JsonNode oAuthMaskedConfigurationJson = oAuthConfigSupplier.maskSourceOAuthParameters(sourceDefinitionId, workspaceId, configurationJson); - final SourceConnection sourceConnection = new SourceConnection() - .withName(name) - .withSourceDefinitionId(sourceDefinitionId) - .withWorkspaceId(workspaceId) - .withSourceId(sourceId) - .withTombstone(tombstone) - .withConfiguration(oAuthMaskedConfigurationJson); - secretsRepositoryWriter.writeSourceConnection(sourceConnection, spec); - } - - protected static SourceRead toSourceRead(final SourceConnection sourceConnection, - final StandardSourceDefinition standardSourceDefinition) { - return new SourceRead() - .sourceDefinitionId(standardSourceDefinition.getSourceDefinitionId()) - .sourceName(standardSourceDefinition.getName()) - .sourceId(sourceConnection.getSourceId()) - .workspaceId(sourceConnection.getWorkspaceId()) - .sourceDefinitionId(sourceConnection.getSourceDefinitionId()) - .connectionConfiguration(sourceConnection.getConfiguration()) - .name(sourceConnection.getName()) - .icon(SourceDefinitionsHandler.loadIcon(standardSourceDefinition.getIcon())); - } - - protected static SourceSnippetRead toSourceSnippetRead(final SourceConnection source, final StandardSourceDefinition sourceDefinition) { - return new SourceSnippetRead() - .sourceId(source.getSourceId()) - .name(source.getName()) - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .sourceName(sourceDefinition.getName()) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/StateHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/StateHandler.java deleted file mode 100644 index 7ca6709634aab..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/StateHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionState; -import io.airbyte.api.model.generated.ConnectionStateCreateOrUpdate; -import io.airbyte.config.StateWrapper; -import io.airbyte.config.persistence.StatePersistence; -import io.airbyte.workers.helper.StateConverter; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.Optional; -import java.util.UUID; - -@Singleton -public class StateHandler { - - private final StatePersistence statePersistence; - - public StateHandler(final StatePersistence statePersistence) { - this.statePersistence = statePersistence; - } - - public ConnectionState getState(final ConnectionIdRequestBody connectionIdRequestBody) throws IOException { - final UUID connectionId = connectionIdRequestBody.getConnectionId(); - final Optional currentState = statePersistence.getCurrentState(connectionId); - return StateConverter.toApi(connectionId, currentState.orElse(null)); - } - - public ConnectionState createOrUpdateState(final ConnectionStateCreateOrUpdate connectionStateCreateOrUpdate) throws IOException { - final UUID connectionId = connectionStateCreateOrUpdate.getConnectionId(); - - final StateWrapper convertedCreateOrUpdate = StateConverter.toInternal(connectionStateCreateOrUpdate.getConnectionState()); - statePersistence.updateOrCreateState(connectionId, convertedCreateOrUpdate); - final Optional newInternalState = statePersistence.getCurrentState(connectionId); - - return StateConverter.toApi(connectionId, newInternalState.orElse(null)); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandler.java deleted file mode 100644 index daedd09fa59d8..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.WebBackendCheckUpdatesRead; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigRepository; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; - -/** - * The web backend is an abstraction that allows the frontend to structure data in such a way that - * it is easier for a react frontend to consume. It should NOT have direct access to the database. - * It should operate exclusively by calling other endpoints that are exposed in the API. - **/ -@Slf4j -@Singleton -public class WebBackendCheckUpdatesHandler { - - private static final int NO_CHANGES_FOUND = 0; - - // todo (cgardens) - this handler should NOT have access to the db. only access via handler. - @Deprecated - final ConfigRepository configRepositoryDoNotUse; - final AirbyteGithubStore githubStore; - - public WebBackendCheckUpdatesHandler(final ConfigRepository configRepositoryDoNotUse, final AirbyteGithubStore githubStore) { - this.configRepositoryDoNotUse = configRepositoryDoNotUse; - this.githubStore = githubStore; - } - - public WebBackendCheckUpdatesRead checkUpdates() { - - final int destinationDiffCount = getDestinationDiffCount(); - final int sourceDiffCount = getSourceDiffCount(); - - return new WebBackendCheckUpdatesRead() - .destinationDefinitions(destinationDiffCount) - .sourceDefinitions(sourceDiffCount); - } - - private int getDestinationDiffCount() { - final List> currentActorDefToDockerImageTag; - final Map newActorDefToDockerImageTag; - - try { - currentActorDefToDockerImageTag = configRepositoryDoNotUse.listStandardDestinationDefinitions(false) - .stream() - .map(def -> Map.entry(def.getDestinationDefinitionId(), def.getDockerImageTag())) - .toList(); - } catch (final IOException e) { - log.error("Failed to get current list of standard destination definitions", e); - return NO_CHANGES_FOUND; - } - - try { - newActorDefToDockerImageTag = githubStore.getLatestDestinations() - .stream() - .collect(Collectors.toMap(StandardDestinationDefinition::getDestinationDefinitionId, StandardDestinationDefinition::getDockerImageTag)); - } catch (final InterruptedException e) { - log.error("Failed to get latest list of standard destination definitions", e); - return NO_CHANGES_FOUND; - } - - return getDiffCount(currentActorDefToDockerImageTag, newActorDefToDockerImageTag); - } - - private int getSourceDiffCount() { - final List> currentActorDefToDockerImageTag; - final Map newActorDefToDockerImageTag; - - try { - currentActorDefToDockerImageTag = configRepositoryDoNotUse.listStandardSourceDefinitions(false) - .stream() - .map(def -> Map.entry(def.getSourceDefinitionId(), def.getDockerImageTag())) - .toList(); - } catch (final IOException e) { - log.error("Failed to get current list of standard source definitions", e); - return NO_CHANGES_FOUND; - } - - try { - newActorDefToDockerImageTag = githubStore.getLatestSources() - .stream() - .collect(Collectors.toMap(StandardSourceDefinition::getSourceDefinitionId, StandardSourceDefinition::getDockerImageTag)); - } catch (final InterruptedException e) { - log.error("Failed to get latest list of standard source definitions", e); - return NO_CHANGES_FOUND; - } - - return getDiffCount(currentActorDefToDockerImageTag, newActorDefToDockerImageTag); - } - - private int getDiffCount(final List> initialSet, final Map newSet) { - int diffCount = 0; - for (final Entry kvp : initialSet) { - final String newDockerImageTag = newSet.get(kvp.getKey()); - if (newDockerImageTag != null && !kvp.getValue().equals(newDockerImageTag)) { - ++diffCount; - } - } - return diffCount; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandler.java deleted file mode 100644 index b863e56cdedbd..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandler.java +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static java.util.stream.Collectors.toMap; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.AirbyteCatalog; -import io.airbyte.api.model.generated.AirbyteStream; -import io.airbyte.api.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.model.generated.AirbyteStreamConfiguration; -import io.airbyte.api.model.generated.CatalogDiff; -import io.airbyte.api.model.generated.ConnectionCreate; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionStateType; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationSnippetRead; -import io.airbyte.api.model.generated.FieldTransform; -import io.airbyte.api.model.generated.JobRead; -import io.airbyte.api.model.generated.OperationCreate; -import io.airbyte.api.model.generated.OperationReadList; -import io.airbyte.api.model.generated.OperationUpdate; -import io.airbyte.api.model.generated.SchemaChange; -import io.airbyte.api.model.generated.SelectedFieldInfo; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRequestBody; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceSnippetRead; -import io.airbyte.api.model.generated.StreamDescriptor; -import io.airbyte.api.model.generated.StreamTransform; -import io.airbyte.api.model.generated.StreamTransform.TransformTypeEnum; -import io.airbyte.api.model.generated.WebBackendConnectionCreate; -import io.airbyte.api.model.generated.WebBackendConnectionListItem; -import io.airbyte.api.model.generated.WebBackendConnectionListRequestBody; -import io.airbyte.api.model.generated.WebBackendConnectionRead; -import io.airbyte.api.model.generated.WebBackendConnectionReadList; -import io.airbyte.api.model.generated.WebBackendConnectionRequestBody; -import io.airbyte.api.model.generated.WebBackendConnectionUpdate; -import io.airbyte.api.model.generated.WebBackendOperationCreateOrUpdate; -import io.airbyte.api.model.generated.WebBackendWorkspaceState; -import io.airbyte.api.model.generated.WebBackendWorkspaceStateResult; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.lang.MoreBooleans; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.config.ActorCatalog; -import io.airbyte.config.ActorCatalogFetchEvent; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardSync; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.ConfigRepository.StandardSyncQuery; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.validation.json.JsonValidationException; -import io.airbyte.workers.helper.ProtocolConverters; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * The web backend is an abstraction that allows the frontend to structure data in such a way that - * it is easier for a react frontend to consume. It should NOT have direct access to the database. - * It should operate exclusively by calling other endpoints that are exposed in the API. - **/ -@Singleton -public class WebBackendConnectionsHandler { - - private final ConnectionsHandler connectionsHandler; - private final StateHandler stateHandler; - private final SourceHandler sourceHandler; - private final DestinationHandler destinationHandler; - private final JobHistoryHandler jobHistoryHandler; - private final SchedulerHandler schedulerHandler; - private final OperationsHandler operationsHandler; - private final EventRunner eventRunner; - // todo (cgardens) - this handler should NOT have access to the db. only access via handler. - @Deprecated - private final ConfigRepository configRepositoryDoNotUse; - - public WebBackendConnectionsHandler(final ConnectionsHandler connectionsHandler, - final StateHandler stateHandler, - final SourceHandler sourceHandler, - final DestinationHandler destinationHandler, - final JobHistoryHandler jobHistoryHandler, - final SchedulerHandler schedulerHandler, - final OperationsHandler operationsHandler, - final EventRunner eventRunner, - final ConfigRepository configRepositoryDoNotUse) { - this.connectionsHandler = connectionsHandler; - this.stateHandler = stateHandler; - this.sourceHandler = sourceHandler; - this.destinationHandler = destinationHandler; - this.jobHistoryHandler = jobHistoryHandler; - this.schedulerHandler = schedulerHandler; - this.operationsHandler = operationsHandler; - this.eventRunner = eventRunner; - this.configRepositoryDoNotUse = configRepositoryDoNotUse; - } - - public WebBackendWorkspaceStateResult getWorkspaceState(final WebBackendWorkspaceState webBackendWorkspaceState) throws IOException { - final var workspaceId = webBackendWorkspaceState.getWorkspaceId(); - final var connectionCount = configRepositoryDoNotUse.countConnectionsForWorkspace(workspaceId); - final var destinationCount = configRepositoryDoNotUse.countDestinationsForWorkspace(workspaceId); - final var sourceCount = configRepositoryDoNotUse.countSourcesForWorkspace(workspaceId); - - return new WebBackendWorkspaceStateResult() - .hasConnections(connectionCount > 0) - .hasDestinations(destinationCount > 0) - .hasSources(sourceCount > 0); - } - - public ConnectionStateType getStateType(final ConnectionIdRequestBody connectionIdRequestBody) throws IOException { - return Enums.convertTo(stateHandler.getState(connectionIdRequestBody).getStateType(), ConnectionStateType.class); - } - - public WebBackendConnectionReadList webBackendListConnectionsForWorkspace(final WebBackendConnectionListRequestBody webBackendConnectionListRequestBody) - throws IOException { - - final StandardSyncQuery query = new StandardSyncQuery( - webBackendConnectionListRequestBody.getWorkspaceId(), - webBackendConnectionListRequestBody.getSourceId(), - webBackendConnectionListRequestBody.getDestinationId(), - // passing 'false' so that deleted connections are not included - false); - - final List standardSyncs = configRepositoryDoNotUse.listWorkspaceStandardSyncs(query); - final List sourceIds = standardSyncs.stream().map(StandardSync::getSourceId).toList(); - final List destinationIds = standardSyncs.stream().map(StandardSync::getDestinationId).toList(); - final List connectionIds = standardSyncs.stream().map(StandardSync::getConnectionId).toList(); - - // Fetching all the related objects we need for the final output - final Map sourceReadById = getSourceSnippetReadById(sourceIds); - final Map destinationReadById = getDestinationSnippetReadById(destinationIds); - final Map latestJobByConnectionId = getLatestJobByConnectionId(connectionIds); - // This call could be removed, running jobs should be a subset of latest jobs, need to expose the - // right status filtering for this. - final Map runningJobByConnectionId = getRunningJobByConnectionId(connectionIds); - final Map newestFetchEventsByActorId = - configRepositoryDoNotUse.getMostRecentActorCatalogFetchEventForSources(sourceIds); - - final List connectionItems = Lists.newArrayList(); - - for (final StandardSync standardSync : standardSyncs) { - connectionItems.add( - buildWebBackendConnectionListItem( - standardSync, - sourceReadById, - destinationReadById, - latestJobByConnectionId, - runningJobByConnectionId, - Optional.ofNullable(newestFetchEventsByActorId.get(standardSync.getSourceId())))); - } - - return new WebBackendConnectionReadList().connections(connectionItems); - } - - private Map getLatestJobByConnectionId(final List connectionIds) throws IOException { - return jobHistoryHandler.getLatestSyncJobsForConnections(connectionIds).stream() - .collect(Collectors.toMap(j -> UUID.fromString(j.getConfigId()), Function.identity())); - } - - private Map getRunningJobByConnectionId(final List connectionIds) throws IOException { - return jobHistoryHandler.getRunningSyncJobForConnections(connectionIds).stream() - .collect(Collectors.toMap(j -> UUID.fromString(j.getConfigId()), Function.identity())); - } - - private Map getSourceSnippetReadById(final List sourceIds) throws IOException { - return configRepositoryDoNotUse.getSourceAndDefinitionsFromSourceIds(sourceIds) - .stream() - .map(sourceAndDefinition -> SourceHandler.toSourceSnippetRead(sourceAndDefinition.source(), sourceAndDefinition.definition())) - .collect(Collectors.toMap(SourceSnippetRead::getSourceId, Function.identity())); - } - - private Map getDestinationSnippetReadById(final List destinationIds) throws IOException { - return configRepositoryDoNotUse.getDestinationAndDefinitionsFromDestinationIds(destinationIds) - .stream() - .map(destinationAndDefinition -> DestinationHandler.toDestinationSnippetRead(destinationAndDefinition.destination(), - destinationAndDefinition.definition())) - .collect(Collectors.toMap(DestinationSnippetRead::getDestinationId, Function.identity())); - } - - private WebBackendConnectionRead buildWebBackendConnectionRead(final ConnectionRead connectionRead, final Optional currentSourceCatalogId) - throws ConfigNotFoundException, IOException, JsonValidationException { - final SourceRead source = getSourceRead(connectionRead.getSourceId()); - final DestinationRead destination = getDestinationRead(connectionRead.getDestinationId()); - final OperationReadList operations = getOperationReadList(connectionRead); - final Optional latestSyncJob = jobHistoryHandler.getLatestSyncJob(connectionRead.getConnectionId()); - final Optional latestRunningSyncJob = jobHistoryHandler.getLatestRunningSyncJob(connectionRead.getConnectionId()); - - final WebBackendConnectionRead webBackendConnectionRead = getWebBackendConnectionRead(connectionRead, source, destination, operations) - .catalogId(connectionRead.getSourceCatalogId()); - - webBackendConnectionRead.setIsSyncing(latestRunningSyncJob.isPresent()); - - latestSyncJob.ifPresent(job -> { - webBackendConnectionRead.setLatestSyncJobCreatedAt(job.getCreatedAt()); - webBackendConnectionRead.setLatestSyncJobStatus(job.getStatus()); - }); - - final Optional mostRecentFetchEvent = - configRepositoryDoNotUse.getMostRecentActorCatalogFetchEventForSource(connectionRead.getSourceId()); - - final SchemaChange schemaChange = getSchemaChange(connectionRead, currentSourceCatalogId, mostRecentFetchEvent); - - webBackendConnectionRead.setSchemaChange(schemaChange); - - return webBackendConnectionRead; - } - - static private WebBackendConnectionListItem buildWebBackendConnectionListItem( - final StandardSync standardSync, - final Map sourceReadById, - final Map destinationReadById, - final Map latestJobByConnectionId, - final Map runningJobByConnectionId, - final Optional latestFetchEvent) { - - final SourceSnippetRead source = sourceReadById.get(standardSync.getSourceId()); - final DestinationSnippetRead destination = destinationReadById.get(standardSync.getDestinationId()); - final Optional latestSyncJob = Optional.ofNullable(latestJobByConnectionId.get(standardSync.getConnectionId())); - final Optional latestRunningSyncJob = Optional.ofNullable(runningJobByConnectionId.get(standardSync.getConnectionId())); - final ConnectionRead connectionRead = ApiPojoConverters.internalToConnectionRead(standardSync); - final Optional currentCatalogId = connectionRead == null ? Optional.empty() : Optional.ofNullable(connectionRead.getSourceCatalogId()); - - final SchemaChange schemaChange = getSchemaChange(connectionRead, currentCatalogId, latestFetchEvent); - - final WebBackendConnectionListItem listItem = new WebBackendConnectionListItem() - .connectionId(standardSync.getConnectionId()) - .status(ApiPojoConverters.toApiStatus(standardSync.getStatus())) - .name(standardSync.getName()) - .scheduleType(ApiPojoConverters.toApiConnectionScheduleType(standardSync)) - .scheduleData(ApiPojoConverters.toApiConnectionScheduleData(standardSync)) - .source(source) - .destination(destination) - .isSyncing(latestRunningSyncJob.isPresent()) - .schemaChange(schemaChange); - - latestSyncJob.ifPresent(job -> { - listItem.setLatestSyncJobCreatedAt(job.getCreatedAt()); - listItem.setLatestSyncJobStatus(job.getStatus()); - }); - - return listItem; - } - - /* - * A breakingChange boolean is stored on the connectionRead object and corresponds to the boolean - * breakingChange field on the connection table. If there is not a breaking change, we still have to - * check whether there is a non-breaking schema change by fetching the most recent - * ActorCatalogFetchEvent. A new ActorCatalogFetchEvent is stored each time there is a source schema - * refresh, so if the most recent ActorCatalogFetchEvent has a different actor catalog than the - * existing actor catalog, there is a schema change. - */ - @VisibleForTesting - static SchemaChange getSchemaChange( - final ConnectionRead connectionRead, - final Optional currentSourceCatalogId, - final Optional mostRecentFetchEvent) { - if (connectionRead == null || currentSourceCatalogId.isEmpty()) { - return SchemaChange.NO_CHANGE; - } - - if (connectionRead.getBreakingChange() != null && connectionRead.getBreakingChange()) { - return SchemaChange.BREAKING; - } - - if (mostRecentFetchEvent.isPresent() && !mostRecentFetchEvent.map(ActorCatalogFetchEvent::getActorCatalogId).equals(currentSourceCatalogId)) { - return SchemaChange.NON_BREAKING; - } - - return SchemaChange.NO_CHANGE; - } - - private SourceRead getSourceRead(final UUID sourceId) throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(sourceId); - return sourceHandler.getSource(sourceIdRequestBody); - } - - private DestinationRead getDestinationRead(final UUID destinationId) - throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody().destinationId(destinationId); - return destinationHandler.getDestination(destinationIdRequestBody); - } - - private OperationReadList getOperationReadList(final ConnectionRead connectionRead) - throws JsonValidationException, IOException, ConfigNotFoundException { - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(connectionRead.getConnectionId()); - return operationsHandler.listOperationsForConnection(connectionIdRequestBody); - } - - private static WebBackendConnectionRead getWebBackendConnectionRead(final ConnectionRead connectionRead, - final SourceRead source, - final DestinationRead destination, - final OperationReadList operations) { - return new WebBackendConnectionRead() - .connectionId(connectionRead.getConnectionId()) - .sourceId(connectionRead.getSourceId()) - .destinationId(connectionRead.getDestinationId()) - .operationIds(connectionRead.getOperationIds()) - .name(connectionRead.getName()) - .namespaceDefinition(connectionRead.getNamespaceDefinition()) - .namespaceFormat(connectionRead.getNamespaceFormat()) - .prefix(connectionRead.getPrefix()) - .syncCatalog(connectionRead.getSyncCatalog()) - .status(connectionRead.getStatus()) - .schedule(connectionRead.getSchedule()) - .scheduleType(connectionRead.getScheduleType()) - .scheduleData(connectionRead.getScheduleData()) - .source(source) - .destination(destination) - .operations(operations.getOperations()) - .resourceRequirements(connectionRead.getResourceRequirements()) - .geography(connectionRead.getGeography()) - .notifySchemaChanges(connectionRead.getNotifySchemaChanges()) - .nonBreakingChangesPreference(connectionRead.getNonBreakingChangesPreference()); - } - - // todo (cgardens) - This logic is a headache to follow it stems from the internal data model not - // tracking selected streams in any reasonable way. We should update that. - public WebBackendConnectionRead webBackendGetConnection(final WebBackendConnectionRequestBody webBackendConnectionRequestBody) - throws ConfigNotFoundException, IOException, JsonValidationException { - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody() - .connectionId(webBackendConnectionRequestBody.getConnectionId()); - - final ConnectionRead connection = connectionsHandler.getConnection(connectionIdRequestBody.getConnectionId()); - - /* - * This variable contains all configuration but will be missing streams that were not selected. - */ - final AirbyteCatalog configuredCatalog = connection.getSyncCatalog(); - /* - * This catalog represents the full catalog that was used to create the configured catalog. It will - * have all streams that were present at the time. It will have no configuration set. - */ - final Optional catalogUsedToMakeConfiguredCatalog = connectionsHandler - .getConnectionAirbyteCatalog(webBackendConnectionRequestBody.getConnectionId()); - - /* - * This catalog represents the full catalog that exists now for the source. It will have no - * configuration set. - */ - final Optional refreshedCatalog; - if (MoreBooleans.isTruthy(webBackendConnectionRequestBody.getWithRefreshedCatalog())) { - refreshedCatalog = getRefreshedSchema(connection.getSourceId(), connection.getConnectionId()); - } else { - refreshedCatalog = Optional.empty(); - } - - final CatalogDiff diff; - final AirbyteCatalog syncCatalog; - final Optional currentSourceCatalogId = Optional.ofNullable(connection.getSourceCatalogId()); - if (refreshedCatalog.isPresent()) { - connection.sourceCatalogId(refreshedCatalog.get().getCatalogId()); - /* - * constructs a full picture of all existing configured + all new / updated streams in the newest - * catalog. - * - * Diffing the catalog used to make the configured catalog gives us the clearest diff between the - * schema when the configured catalog was made and now. In the case where we do not have the - * original catalog used to make the configured catalog, we make due, but using the configured - * catalog itself. The drawback is that any stream that was not selected in the configured catalog - * but was present at time of configuration will appear in the diff as an added stream which is - * confusing. We need to figure out why source_catalog_id is not always populated in the db. - */ - syncCatalog = updateSchemaWithRefreshedDiscoveredCatalog(configuredCatalog, catalogUsedToMakeConfiguredCatalog.orElse(configuredCatalog), - refreshedCatalog.get().getCatalog()); - - diff = refreshedCatalog.get().getCatalogDiff(); - connection.setBreakingChange(refreshedCatalog.get().getBreakingChange()); - connection.setStatus(refreshedCatalog.get().getConnectionStatus()); - } else if (catalogUsedToMakeConfiguredCatalog.isPresent()) { - // reconstructs a full picture of the full schema at the time the catalog was configured. - syncCatalog = updateSchemaWithOriginalDiscoveredCatalog(configuredCatalog, catalogUsedToMakeConfiguredCatalog.get()); - // diff not relevant if there was no refresh. - diff = null; - } else { - // fallback. over time this should be rarely used because source_catalog_id should always be set. - syncCatalog = configuredCatalog; - // diff not relevant if there was no refresh. - diff = null; - } - - connection.setSyncCatalog(syncCatalog); - return buildWebBackendConnectionRead(connection, currentSourceCatalogId).catalogDiff(diff); - } - - private AirbyteCatalog updateSchemaWithOriginalDiscoveredCatalog(final AirbyteCatalog configuredCatalog, - final AirbyteCatalog originalDiscoveredCatalog) { - // We pass the original discovered catalog in as the "new" discovered catalog. - return updateSchemaWithRefreshedDiscoveredCatalog(configuredCatalog, originalDiscoveredCatalog, originalDiscoveredCatalog); - } - - private Optional getRefreshedSchema(final UUID sourceId, final UUID connectionId) - throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceDiscoverSchemaRequestBody discoverSchemaReadReq = new SourceDiscoverSchemaRequestBody() - .sourceId(sourceId) - .disableCache(true) - .connectionId(connectionId) - .notifySchemaChange(false); - final SourceDiscoverSchemaRead schemaRead = schedulerHandler.discoverSchemaForSourceFromSourceId(discoverSchemaReadReq); - return Optional.ofNullable(schemaRead); - } - - /** - * Applies existing configurations to a newly discovered catalog. For example, if the users stream - * is in the old and new catalog, any configuration that was previously set for users, we add to the - * new catalog. - * - * @param originalConfigured fully configured, original catalog - * @param originalDiscovered the original discovered catalog used to make the original configured - * catalog - * @param discovered newly discovered catalog, no configurations set - * @return merged catalog, most up-to-date schema with most up-to-date configurations from old - * catalog - */ - @VisibleForTesting - protected static AirbyteCatalog updateSchemaWithRefreshedDiscoveredCatalog(final AirbyteCatalog originalConfigured, - final AirbyteCatalog originalDiscovered, - final AirbyteCatalog discovered) { - /* - * We can't directly use s.getStream() as the key, because it contains a bunch of other fields, so - * we just define a quick-and-dirty record class. - */ - final Map streamDescriptorToOriginalStream = originalConfigured.getStreams() - .stream() - .collect(toMap(s -> new Stream(s.getStream().getName(), s.getStream().getNamespace()), s -> s)); - final Map streamDescriptorToOriginalDiscoveredStream = originalDiscovered.getStreams() - .stream() - .collect(toMap(s -> new Stream(s.getStream().getName(), s.getStream().getNamespace()), s -> s)); - - final List streams = new ArrayList<>(); - - for (final AirbyteStreamAndConfiguration discoveredStream : discovered.getStreams()) { - final AirbyteStream stream = discoveredStream.getStream(); - final AirbyteStreamAndConfiguration originalConfiguredStream = streamDescriptorToOriginalStream.get( - new Stream(stream.getName(), stream.getNamespace())); - final AirbyteStreamAndConfiguration originalDiscoveredStream = streamDescriptorToOriginalDiscoveredStream.get( - new Stream(stream.getName(), stream.getNamespace())); - final AirbyteStreamConfiguration outputStreamConfig; - - if (originalConfiguredStream != null) { - final AirbyteStreamConfiguration originalStreamConfig = originalConfiguredStream.getConfig(); - final AirbyteStreamConfiguration discoveredStreamConfig = discoveredStream.getConfig(); - outputStreamConfig = new AirbyteStreamConfiguration(); - - if (stream.getSupportedSyncModes().contains(originalStreamConfig.getSyncMode())) { - outputStreamConfig.setSyncMode(originalStreamConfig.getSyncMode()); - } else { - outputStreamConfig.setSyncMode(discoveredStreamConfig.getSyncMode()); - } - - if (originalStreamConfig.getCursorField().size() > 0) { - outputStreamConfig.setCursorField(originalStreamConfig.getCursorField()); - } else { - outputStreamConfig.setCursorField(discoveredStreamConfig.getCursorField()); - } - - outputStreamConfig.setDestinationSyncMode(originalStreamConfig.getDestinationSyncMode()); - if (originalStreamConfig.getPrimaryKey().size() > 0) { - outputStreamConfig.setPrimaryKey(originalStreamConfig.getPrimaryKey()); - } else { - outputStreamConfig.setPrimaryKey(discoveredStreamConfig.getPrimaryKey()); - } - - outputStreamConfig.setAliasName(originalStreamConfig.getAliasName()); - outputStreamConfig.setSelected(originalConfiguredStream.getConfig().getSelected()); - - outputStreamConfig.setFieldSelectionEnabled(originalStreamConfig.getFieldSelectionEnabled()); - if (outputStreamConfig.getFieldSelectionEnabled()) { - // TODO(mfsiega-airbyte): support nested fields. - // If field selection is enabled, populate the selected fields. - final Set originallyDiscovered = new HashSet<>(); - final Set refreshDiscovered = new HashSet<>(); - // NOTE: by only taking the first element of the path, we're restricting to top-level fields. - final Set originallySelected = new HashSet<>( - originalConfiguredStream.getConfig().getSelectedFields().stream().map((field) -> field.getFieldPath().get(0)).toList()); - originalDiscoveredStream.getStream().getJsonSchema().findPath("properties").fieldNames() - .forEachRemaining((name) -> originallyDiscovered.add(name)); - stream.getJsonSchema().findPath("properties").fieldNames().forEachRemaining((name) -> refreshDiscovered.add(name)); - // We include a selected field if it: - // (is in the newly discovered schema) AND (it was either originally selected OR not in the - // originally discovered schema at all) - // NOTE: this implies that the default behaviour for newly-discovered columns is to add them. - for (final String discoveredField : refreshDiscovered) { - if (originallySelected.contains(discoveredField) || !originallyDiscovered.contains(discoveredField)) { - outputStreamConfig.addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem(discoveredField)); - } - } - } - - } else { - outputStreamConfig = discoveredStream.getConfig(); - outputStreamConfig.setSelected(false); - } - final AirbyteStreamAndConfiguration outputStream = new AirbyteStreamAndConfiguration() - .stream(Jsons.clone(stream)) - .config(outputStreamConfig); - streams.add(outputStream); - } - return new AirbyteCatalog().streams(streams); - } - - public WebBackendConnectionRead webBackendCreateConnection(final WebBackendConnectionCreate webBackendConnectionCreate) - throws ConfigNotFoundException, IOException, JsonValidationException { - final List operationIds = createOperations(webBackendConnectionCreate); - - final ConnectionCreate connectionCreate = toConnectionCreate(webBackendConnectionCreate, operationIds); - final Optional currentSourceCatalogId = Optional.ofNullable(connectionCreate.getSourceCatalogId()); - return buildWebBackendConnectionRead(connectionsHandler.createConnection(connectionCreate), currentSourceCatalogId); - } - - /** - * Given a WebBackendConnectionUpdate, patch the connection by applying any non-null properties from - * the patch to the connection. - * - * As a convenience to the front-end, this endpoint also creates new operations present in the - * request, and bundles those newly-created operationIds into the connection update. - */ - public WebBackendConnectionRead webBackendUpdateConnection(final WebBackendConnectionUpdate webBackendConnectionPatch) - throws ConfigNotFoundException, IOException, JsonValidationException { - - final UUID connectionId = webBackendConnectionPatch.getConnectionId(); - final ConnectionRead originalConnectionRead = connectionsHandler.getConnection(connectionId); - boolean breakingChange = originalConnectionRead.getBreakingChange() != null && originalConnectionRead.getBreakingChange(); - - // If there have been changes to the sync catalog, check whether these changes result in or fix a - // broken connection - if (webBackendConnectionPatch.getSyncCatalog() != null) { - // Get the most recent actor catalog fetched for this connection's source and the newly updated sync - // catalog - final Optional mostRecentActorCatalog = - configRepositoryDoNotUse.getMostRecentActorCatalogForSource(originalConnectionRead.getSourceId()); - final AirbyteCatalog newAirbyteCatalog = webBackendConnectionPatch.getSyncCatalog(); - // Get the diff between these two catalogs to check for breaking changes - if (mostRecentActorCatalog.isPresent()) { - final io.airbyte.protocol.models.AirbyteCatalog mostRecentAirbyteCatalog = - Jsons.object(mostRecentActorCatalog.get().getCatalog(), io.airbyte.protocol.models.AirbyteCatalog.class); - final StandardSourceDefinition sourceDefinition = - configRepositoryDoNotUse.getSourceDefinitionFromSource(originalConnectionRead.getSourceId()); - final CatalogDiff catalogDiff = - connectionsHandler.getDiff(newAirbyteCatalog, CatalogConverter.toApi(mostRecentAirbyteCatalog, sourceDefinition), - CatalogConverter.toConfiguredProtocol(newAirbyteCatalog)); - breakingChange = containsBreakingChange(catalogDiff); - } - } - - // before doing any updates, fetch the existing catalog so that it can be diffed - // with the final catalog to determine which streams might need to be reset. - final ConfiguredAirbyteCatalog oldConfiguredCatalog = - configRepositoryDoNotUse.getConfiguredCatalogForConnection(connectionId); - - final List newAndExistingOperationIds = createOrUpdateOperations(originalConnectionRead, webBackendConnectionPatch); - - // pass in operationIds because the patch object doesn't include operationIds that were just created - // above. - final ConnectionUpdate connectionPatch = toConnectionPatch(webBackendConnectionPatch, newAndExistingOperationIds, breakingChange); - - // persist the update and set the connectionRead to the updated form. - final ConnectionRead updatedConnectionRead = connectionsHandler.updateConnection(connectionPatch); - - // detect if any streams need to be reset based on the patch and initial catalog, if so, reset them - resetStreamsIfNeeded(webBackendConnectionPatch, oldConfiguredCatalog, updatedConnectionRead, originalConnectionRead); - /* - * This catalog represents the full catalog that was used to create the configured catalog. It will - * have all streams that were present at the time. It will have no configuration set. - */ - final Optional catalogUsedToMakeConfiguredCatalog = connectionsHandler - .getConnectionAirbyteCatalog(connectionId); - if (catalogUsedToMakeConfiguredCatalog.isPresent()) { - // Update the Catalog returned to include all streams, including disabled ones - final AirbyteCatalog syncCatalog = - updateSchemaWithRefreshedDiscoveredCatalog(updatedConnectionRead.getSyncCatalog(), catalogUsedToMakeConfiguredCatalog.get(), - catalogUsedToMakeConfiguredCatalog.get()); - updatedConnectionRead.setSyncCatalog(syncCatalog); - } - - final Optional currentSourceCatalogId = Optional.ofNullable(updatedConnectionRead.getSourceCatalogId()); - return buildWebBackendConnectionRead(updatedConnectionRead, currentSourceCatalogId); - } - - /** - * Given a fully updated connection, check for a diff between the old catalog and the updated - * catalog to see if any streams need to be reset. - */ - private void resetStreamsIfNeeded(final WebBackendConnectionUpdate webBackendConnectionPatch, - final ConfiguredAirbyteCatalog oldConfiguredCatalog, - final ConnectionRead updatedConnectionRead, - final ConnectionRead oldConnectionRead) - throws IOException, JsonValidationException, ConfigNotFoundException { - - final UUID connectionId = webBackendConnectionPatch.getConnectionId(); - final Boolean skipReset = webBackendConnectionPatch.getSkipReset() != null ? webBackendConnectionPatch.getSkipReset() : false; - if (!skipReset) { - final AirbyteCatalog apiExistingCatalog = CatalogConverter.toApi(oldConfiguredCatalog, - CatalogConverter.getFieldSelectionData(oldConnectionRead.getSyncCatalog())); - final AirbyteCatalog upToDateAirbyteCatalog = updatedConnectionRead.getSyncCatalog(); - final CatalogDiff catalogDiff = - connectionsHandler.getDiff(apiExistingCatalog, upToDateAirbyteCatalog, CatalogConverter.toConfiguredProtocol(upToDateAirbyteCatalog)); - final List apiStreamsToReset = getStreamsToReset(catalogDiff); - final Set changedConfigStreamDescriptors = - connectionsHandler.getConfigurationDiff(apiExistingCatalog, upToDateAirbyteCatalog); - final Set allStreamToReset = new HashSet<>(); - allStreamToReset.addAll(apiStreamsToReset); - allStreamToReset.addAll(changedConfigStreamDescriptors); - List streamsToReset = - allStreamToReset.stream().map(ProtocolConverters::streamDescriptorToProtocol).toList(); - - if (!streamsToReset.isEmpty()) { - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(connectionId); - final ConnectionStateType stateType = getStateType(connectionIdRequestBody); - - if (stateType == ConnectionStateType.LEGACY || stateType == ConnectionStateType.NOT_SET) { - streamsToReset = configRepositoryDoNotUse.getAllStreamsForConnection(connectionId); - } - eventRunner.resetConnection( - connectionId, - streamsToReset, true); - } - } - } - - private List createOperations(final WebBackendConnectionCreate webBackendConnectionCreate) - throws JsonValidationException, ConfigNotFoundException, IOException { - if (webBackendConnectionCreate.getOperations() == null) { - return Collections.emptyList(); - } - final List operationIds = new ArrayList<>(); - for (final var operationCreate : webBackendConnectionCreate.getOperations()) { - operationIds.add(operationsHandler.createOperation(operationCreate).getOperationId()); - } - return operationIds; - } - - private List createOrUpdateOperations(final ConnectionRead connectionRead, final WebBackendConnectionUpdate webBackendConnectionPatch) - throws JsonValidationException, ConfigNotFoundException, IOException { - - // this is a patch-style update, so don't make any changes if the request doesn't include operations - if (webBackendConnectionPatch.getOperations() == null) { - return null; - } - - // wrap operationIds in a new ArrayList so that it is modifiable below, when calling .removeAll - final List originalOperationIds = - connectionRead.getOperationIds() == null ? new ArrayList<>() : new ArrayList<>(connectionRead.getOperationIds()); - - final List updatedOperations = webBackendConnectionPatch.getOperations(); - final List finalOperationIds = new ArrayList<>(); - - for (final var operationCreateOrUpdate : updatedOperations) { - if (operationCreateOrUpdate.getOperationId() == null || !originalOperationIds.contains(operationCreateOrUpdate.getOperationId())) { - final OperationCreate operationCreate = toOperationCreate(operationCreateOrUpdate); - finalOperationIds.add(operationsHandler.createOperation(operationCreate).getOperationId()); - } else { - final OperationUpdate operationUpdate = toOperationUpdate(operationCreateOrUpdate); - finalOperationIds.add(operationsHandler.updateOperation(operationUpdate).getOperationId()); - } - } - - // remove operationIds that weren't included in the update - originalOperationIds.removeAll(finalOperationIds); - operationsHandler.deleteOperationsForConnection(connectionRead.getConnectionId(), originalOperationIds); - return finalOperationIds; - } - - @VisibleForTesting - protected static OperationCreate toOperationCreate(final WebBackendOperationCreateOrUpdate operationCreateOrUpdate) { - final OperationCreate operationCreate = new OperationCreate(); - - operationCreate.name(operationCreateOrUpdate.getName()); - operationCreate.workspaceId(operationCreateOrUpdate.getWorkspaceId()); - operationCreate.operatorConfiguration(operationCreateOrUpdate.getOperatorConfiguration()); - - return operationCreate; - } - - @VisibleForTesting - protected static OperationUpdate toOperationUpdate(final WebBackendOperationCreateOrUpdate operationCreateOrUpdate) { - final OperationUpdate operationUpdate = new OperationUpdate(); - - operationUpdate.operationId(operationCreateOrUpdate.getOperationId()); - operationUpdate.name(operationCreateOrUpdate.getName()); - operationUpdate.operatorConfiguration(operationCreateOrUpdate.getOperatorConfiguration()); - - return operationUpdate; - } - - @VisibleForTesting - protected static ConnectionCreate toConnectionCreate(final WebBackendConnectionCreate webBackendConnectionCreate, final List operationIds) { - final ConnectionCreate connectionCreate = new ConnectionCreate(); - - connectionCreate.name(webBackendConnectionCreate.getName()); - connectionCreate.namespaceDefinition(webBackendConnectionCreate.getNamespaceDefinition()); - connectionCreate.namespaceFormat(webBackendConnectionCreate.getNamespaceFormat()); - connectionCreate.prefix(webBackendConnectionCreate.getPrefix()); - connectionCreate.sourceId(webBackendConnectionCreate.getSourceId()); - connectionCreate.destinationId(webBackendConnectionCreate.getDestinationId()); - connectionCreate.operationIds(operationIds); - connectionCreate.syncCatalog(webBackendConnectionCreate.getSyncCatalog()); - connectionCreate.schedule(webBackendConnectionCreate.getSchedule()); - connectionCreate.scheduleType(webBackendConnectionCreate.getScheduleType()); - connectionCreate.scheduleData(webBackendConnectionCreate.getScheduleData()); - connectionCreate.status(webBackendConnectionCreate.getStatus()); - connectionCreate.resourceRequirements(webBackendConnectionCreate.getResourceRequirements()); - connectionCreate.sourceCatalogId(webBackendConnectionCreate.getSourceCatalogId()); - connectionCreate.geography(webBackendConnectionCreate.getGeography()); - connectionCreate.nonBreakingChangesPreference(webBackendConnectionCreate.getNonBreakingChangesPreference()); - - return connectionCreate; - } - - /** - * Take in a WebBackendConnectionUpdate and convert it into a ConnectionUpdate. OperationIds are - * handled as a special case because the WebBackendConnectionUpdate handler allows for on-the-fly - * creation of new operations. So, the brand-new IDs are passed in because they aren't present in - * the WebBackendConnectionUpdate itself. - * - * The return value is used as a patch -- a field set to null means that it should not be modified. - */ - @VisibleForTesting - protected static ConnectionUpdate toConnectionPatch(final WebBackendConnectionUpdate webBackendConnectionPatch, - final List finalOperationIds, - final boolean breakingChange) { - final ConnectionUpdate connectionPatch = new ConnectionUpdate(); - - connectionPatch.connectionId(webBackendConnectionPatch.getConnectionId()); - connectionPatch.namespaceDefinition(webBackendConnectionPatch.getNamespaceDefinition()); - connectionPatch.namespaceFormat(webBackendConnectionPatch.getNamespaceFormat()); - connectionPatch.prefix(webBackendConnectionPatch.getPrefix()); - connectionPatch.name(webBackendConnectionPatch.getName()); - connectionPatch.syncCatalog(webBackendConnectionPatch.getSyncCatalog()); - connectionPatch.schedule(webBackendConnectionPatch.getSchedule()); - connectionPatch.scheduleType(webBackendConnectionPatch.getScheduleType()); - connectionPatch.scheduleData(webBackendConnectionPatch.getScheduleData()); - connectionPatch.status(webBackendConnectionPatch.getStatus()); - connectionPatch.resourceRequirements(webBackendConnectionPatch.getResourceRequirements()); - connectionPatch.sourceCatalogId(webBackendConnectionPatch.getSourceCatalogId()); - connectionPatch.geography(webBackendConnectionPatch.getGeography()); - connectionPatch.notifySchemaChanges(webBackendConnectionPatch.getNotifySchemaChanges()); - connectionPatch.nonBreakingChangesPreference(webBackendConnectionPatch.getNonBreakingChangesPreference()); - connectionPatch.breakingChange(breakingChange); - - connectionPatch.operationIds(finalOperationIds); - - return connectionPatch; - } - - @VisibleForTesting - static List getStreamsToReset(final CatalogDiff catalogDiff) { - return catalogDiff.getTransforms().stream().map(StreamTransform::getStreamDescriptor).toList(); - } - - /** - * Equivalent to {@see io.airbyte.integrations.base.AirbyteStreamNameNamespacePair}. Intentionally - * not using that class because it doesn't make sense for airbyte-server to depend on - * base-java-integration. - */ - private record Stream(String name, String namespace) { - - } - - private boolean containsBreakingChange(final CatalogDiff diff) { - for (final StreamTransform streamTransform : diff.getTransforms()) { - if (streamTransform.getTransformType() != TransformTypeEnum.UPDATE_STREAM) { - continue; - } - - final boolean anyBreakingFieldTransforms = streamTransform.getUpdateStream().stream().anyMatch(FieldTransform::getBreaking); - if (anyBreakingFieldTransforms) { - return true; - } - } - - return false; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandler.java deleted file mode 100644 index 70379fb553f78..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.Geography; -import io.airbyte.api.model.generated.WebBackendGeographiesListResult; -import jakarta.inject.Singleton; -import java.util.Arrays; -import java.util.Collections; - -/** - * The web backend is an abstraction that allows the frontend to structure data in such a way that - * it is easier for a react frontend to consume. It should NOT have direct access to the database. - * It should operate exclusively by calling other endpoints that are exposed in the API. - **/ -@Singleton -public class WebBackendGeographiesHandler { - - public WebBackendGeographiesListResult listGeographiesOSS() { - // for now, OSS only supports AUTO. This can evolve to account for complex OSS use cases, but for - // now we expect OSS deployments to use a single default Task Queue for scheduling syncs in a vast - // majority of cases. - return new WebBackendGeographiesListResult().geographies( - Collections.singletonList(Geography.AUTO)); - } - - /** - * Only called by the wrapped Cloud API to enable multi-cloud - */ - public WebBackendGeographiesListResult listGeographiesCloud() { - return new WebBackendGeographiesListResult().geographies(Arrays.asList(Geography.values())); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WorkspacesHandler.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WorkspacesHandler.java deleted file mode 100644 index 9cc35fcd7ff75..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/WorkspacesHandler.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import com.github.slugify.Slugify; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import io.airbyte.analytics.TrackingClientSingleton; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.Geography; -import io.airbyte.api.model.generated.SlugRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.WorkspaceCreate; -import io.airbyte.api.model.generated.WorkspaceGiveFeedback; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.api.model.generated.WorkspaceRead; -import io.airbyte.api.model.generated.WorkspaceReadList; -import io.airbyte.api.model.generated.WorkspaceUpdate; -import io.airbyte.api.model.generated.WorkspaceUpdateName; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.server.converters.NotificationConverter; -import io.airbyte.commons.server.converters.WorkspaceWebhookConfigsConverter; -import io.airbyte.commons.server.errors.InternalServerKnownException; -import io.airbyte.commons.server.errors.ValueConflictKnownException; -import io.airbyte.config.StandardWorkspace; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.validation.json.JsonValidationException; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import org.apache.commons.lang3.RandomStringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class WorkspacesHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(WorkspacesHandler.class); - private final ConfigRepository configRepository; - private final SecretsRepositoryWriter secretsRepositoryWriter; - private final ConnectionsHandler connectionsHandler; - private final DestinationHandler destinationHandler; - private final SourceHandler sourceHandler; - private final Supplier uuidSupplier; - private final Slugify slugify; - - @Inject - public WorkspacesHandler(final ConfigRepository configRepository, - final SecretsRepositoryWriter secretsRepositoryWriter, - final ConnectionsHandler connectionsHandler, - final DestinationHandler destinationHandler, - final SourceHandler sourceHandler) { - this(configRepository, secretsRepositoryWriter, connectionsHandler, destinationHandler, sourceHandler, UUID::randomUUID); - } - - @VisibleForTesting - WorkspacesHandler(final ConfigRepository configRepository, - final SecretsRepositoryWriter secretsRepositoryWriter, - final ConnectionsHandler connectionsHandler, - final DestinationHandler destinationHandler, - final SourceHandler sourceHandler, - final Supplier uuidSupplier) { - this.configRepository = configRepository; - this.secretsRepositoryWriter = secretsRepositoryWriter; - this.connectionsHandler = connectionsHandler; - this.destinationHandler = destinationHandler; - this.sourceHandler = sourceHandler; - this.uuidSupplier = uuidSupplier; - this.slugify = new Slugify(); - } - - public WorkspaceRead createWorkspace(final WorkspaceCreate workspaceCreate) - throws JsonValidationException, IOException, ValueConflictKnownException { - - final String email = workspaceCreate.getEmail(); - final Boolean anonymousDataCollection = workspaceCreate.getAnonymousDataCollection(); - final Boolean news = workspaceCreate.getNews(); - final Boolean securityUpdates = workspaceCreate.getSecurityUpdates(); - final Boolean displaySetupWizard = workspaceCreate.getDisplaySetupWizard(); - - // if not set on the workspaceCreate, set the defaultGeography to AUTO - final io.airbyte.config.Geography defaultGeography = workspaceCreate.getDefaultGeography() != null - ? Enums.convertTo(workspaceCreate.getDefaultGeography(), io.airbyte.config.Geography.class) - : io.airbyte.config.Geography.AUTO; - - final StandardWorkspace workspace = new StandardWorkspace() - .withWorkspaceId(uuidSupplier.get()) - .withCustomerId(uuidSupplier.get()) - .withName(workspaceCreate.getName()) - .withSlug(generateUniqueSlug(workspaceCreate.getName())) - .withInitialSetupComplete(false) - .withAnonymousDataCollection(anonymousDataCollection != null ? anonymousDataCollection : false) - .withNews(news != null ? news : false) - .withSecurityUpdates(securityUpdates != null ? securityUpdates : false) - .withDisplaySetupWizard(displaySetupWizard != null ? displaySetupWizard : false) - .withTombstone(false) - .withNotifications(NotificationConverter.toConfigList(workspaceCreate.getNotifications())) - .withDefaultGeography(defaultGeography) - .withWebhookOperationConfigs(WorkspaceWebhookConfigsConverter.toPersistenceWrite(workspaceCreate.getWebhookConfigs(), uuidSupplier)); - - if (!Strings.isNullOrEmpty(email)) { - workspace.withEmail(email); - } - - return persistStandardWorkspace(workspace); - } - - public void deleteWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // get existing implementation - final StandardWorkspace persistedWorkspace = configRepository.getStandardWorkspaceNoSecrets(workspaceIdRequestBody.getWorkspaceId(), false); - - // disable all connections associated with this workspace - for (final ConnectionRead connectionRead : connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody).getConnections()) { - connectionsHandler.deleteConnection(connectionRead.getConnectionId()); - } - - // disable all destinations associated with this workspace - for (final DestinationRead destinationRead : destinationHandler.listDestinationsForWorkspace(workspaceIdRequestBody).getDestinations()) { - destinationHandler.deleteDestination(destinationRead); - } - - // disable all sources associated with this workspace - for (final SourceRead sourceRead : sourceHandler.listSourcesForWorkspace(workspaceIdRequestBody).getSources()) { - sourceHandler.deleteSource(sourceRead); - } - - persistedWorkspace.withTombstone(true); - persistStandardWorkspace(persistedWorkspace); - } - - public WorkspaceReadList listWorkspaces() throws JsonValidationException, IOException { - final List reads = configRepository.listStandardWorkspaces(false).stream() - .map(WorkspacesHandler::buildWorkspaceRead) - .collect(Collectors.toList()); - return new WorkspaceReadList().workspaces(reads); - } - - public WorkspaceRead getWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - final UUID workspaceId = workspaceIdRequestBody.getWorkspaceId(); - final StandardWorkspace workspace = configRepository.getStandardWorkspaceNoSecrets(workspaceId, false); - return buildWorkspaceRead(workspace); - } - - @SuppressWarnings("unused") - public WorkspaceRead getWorkspaceBySlug(final SlugRequestBody slugRequestBody) - throws JsonValidationException, IOException, ConfigNotFoundException { - // for now we assume there is one workspace and it has a default uuid. - final StandardWorkspace workspace = configRepository.getWorkspaceBySlug(slugRequestBody.getSlug(), false); - return buildWorkspaceRead(workspace); - } - - public WorkspaceRead getWorkspaceByConnectionId(final ConnectionIdRequestBody connectionIdRequestBody) { - final StandardWorkspace workspace = configRepository.getStandardWorkspaceFromConnection(connectionIdRequestBody.getConnectionId(), false); - return buildWorkspaceRead(workspace); - } - - public WorkspaceRead updateWorkspace(final WorkspaceUpdate workspacePatch) throws ConfigNotFoundException, IOException, JsonValidationException { - final UUID workspaceId = workspacePatch.getWorkspaceId(); - - LOGGER.debug("Starting updateWorkspace for workspaceId {}...", workspaceId); - LOGGER.debug("Incoming workspacePatch: {}", workspacePatch); - - final StandardWorkspace workspace = configRepository.getStandardWorkspaceNoSecrets(workspaceId, false); - LOGGER.debug("Initial workspace: {}", workspace); - - validateWorkspacePatch(workspace, workspacePatch); - - LOGGER.debug("Initial WorkspaceRead: {}", buildWorkspaceRead(workspace)); - - applyPatchToStandardWorkspace(workspace, workspacePatch); - - LOGGER.debug("Patched Workspace before persisting: {}", workspace); - - if (workspacePatch.getWebhookConfigs() == null) { - // We aren't persisting any secrets. It's safe (and necessary) to use the NoSecrets variant because - // we never hydrated them in the first place. - configRepository.writeStandardWorkspaceNoSecrets(workspace); - } else { - // We're saving new webhook configs, so we need to persist the secrets. - persistStandardWorkspace(workspace); - } - - // after updating email or tracking info, we need to re-identify the instance. - TrackingClientSingleton.get().identify(workspaceId); - - return buildWorkspaceReadFromId(workspaceId); - } - - public WorkspaceRead updateWorkspaceName(final WorkspaceUpdateName workspaceUpdateName) - throws JsonValidationException, ConfigNotFoundException, IOException { - final UUID workspaceId = workspaceUpdateName.getWorkspaceId(); - - final StandardWorkspace persistedWorkspace = configRepository.getStandardWorkspaceNoSecrets(workspaceId, false); - - persistedWorkspace - .withName(workspaceUpdateName.getName()) - .withSlug(generateUniqueSlug(workspaceUpdateName.getName())); - - // NOTE: it's safe (and necessary) to use the NoSecrets variant because we never hydrated them in - // the first place. - configRepository.writeStandardWorkspaceNoSecrets(persistedWorkspace); - - return buildWorkspaceReadFromId(workspaceId); - } - - public void setFeedbackDone(final WorkspaceGiveFeedback workspaceGiveFeedback) - throws JsonValidationException, ConfigNotFoundException, IOException { - configRepository.setFeedback(workspaceGiveFeedback.getWorkspaceId()); - } - - private WorkspaceRead buildWorkspaceReadFromId(final UUID workspaceId) throws ConfigNotFoundException, IOException, JsonValidationException { - final StandardWorkspace workspace = configRepository.getStandardWorkspaceNoSecrets(workspaceId, false); - return buildWorkspaceRead(workspace); - } - - private String generateUniqueSlug(final String workspaceName) throws JsonValidationException, IOException { - final String proposedSlug = slugify.slugify(workspaceName); - - // todo (cgardens) - this is going to be too expensive once there are too many workspaces. needs to - // be replaced with an actual sql query. e.g. SELECT COUNT(*) WHERE slug=%s; - boolean isSlugUsed = configRepository.getWorkspaceBySlugOptional(proposedSlug, true).isPresent(); - String resolvedSlug = proposedSlug; - final int MAX_ATTEMPTS = 10; - int count = 0; - while (isSlugUsed) { - // todo (cgardens) - this is still susceptible to a race condition where we randomly generate the - // same slug in two different threads. this should be very unlikely. we can fix this by exposing - // database transaction, but that is not something we can do quickly. - resolvedSlug = proposedSlug + "-" + RandomStringUtils.randomAlphabetic(8); - isSlugUsed = configRepository.getWorkspaceBySlugOptional(resolvedSlug, true).isPresent(); - count++; - if (count > MAX_ATTEMPTS) { - throw new InternalServerKnownException(String.format("could not generate a valid slug after %s tries.", MAX_ATTEMPTS)); - } - } - - return resolvedSlug; - } - - private static WorkspaceRead buildWorkspaceRead(final StandardWorkspace workspace) { - final WorkspaceRead result = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(workspace.getEmail()) - .name(workspace.getName()) - .slug(workspace.getSlug()) - .initialSetupComplete(workspace.getInitialSetupComplete()) - .displaySetupWizard(workspace.getDisplaySetupWizard()) - .anonymousDataCollection(workspace.getAnonymousDataCollection()) - .news(workspace.getNews()) - .securityUpdates(workspace.getSecurityUpdates()) - .notifications(NotificationConverter.toApiList(workspace.getNotifications())) - .defaultGeography(Enums.convertTo(workspace.getDefaultGeography(), Geography.class)); - // Add read-only webhook configs. - if (workspace.getWebhookOperationConfigs() != null) { - result.setWebhookConfigs(WorkspaceWebhookConfigsConverter.toApiReads(workspace.getWebhookOperationConfigs())); - } - return result; - } - - private void validateWorkspacePatch(final StandardWorkspace persistedWorkspace, final WorkspaceUpdate workspacePatch) { - Preconditions.checkArgument(persistedWorkspace.getWorkspaceId().equals(workspacePatch.getWorkspaceId())); - } - - private void applyPatchToStandardWorkspace(final StandardWorkspace workspace, final WorkspaceUpdate workspacePatch) { - if (workspacePatch.getAnonymousDataCollection() != null) { - workspace.setAnonymousDataCollection(workspacePatch.getAnonymousDataCollection()); - } - if (workspacePatch.getNews() != null) { - workspace.setNews(workspacePatch.getNews()); - } - if (workspacePatch.getDisplaySetupWizard() != null) { - workspace.setDisplaySetupWizard(workspacePatch.getDisplaySetupWizard()); - } - if (workspacePatch.getSecurityUpdates() != null) { - workspace.setSecurityUpdates(workspacePatch.getSecurityUpdates()); - } - if (!Strings.isNullOrEmpty(workspacePatch.getEmail())) { - workspace.setEmail(workspacePatch.getEmail()); - } - if (workspacePatch.getInitialSetupComplete() != null) { - workspace.setInitialSetupComplete(workspacePatch.getInitialSetupComplete()); - } - if (workspacePatch.getNotifications() != null) { - workspace.setNotifications(NotificationConverter.toConfigList(workspacePatch.getNotifications())); - } - if (workspacePatch.getDefaultGeography() != null) { - workspace.setDefaultGeography(ApiPojoConverters.toPersistenceGeography(workspacePatch.getDefaultGeography())); - } - if (workspacePatch.getWebhookConfigs() != null) { - workspace.setWebhookOperationConfigs(WorkspaceWebhookConfigsConverter.toPersistenceWrite(workspacePatch.getWebhookConfigs(), uuidSupplier)); - } - } - - private WorkspaceRead persistStandardWorkspace(final StandardWorkspace workspace) throws JsonValidationException, IOException { - secretsRepositoryWriter.writeWorkspace(workspace); - return buildWorkspaceRead(workspace); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/CatalogConverter.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/CatalogConverter.java deleted file mode 100644 index 0bdce39387e7c..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/CatalogConverter.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.airbyte.api.model.generated.AirbyteCatalog; -import io.airbyte.api.model.generated.AirbyteStream; -import io.airbyte.api.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.model.generated.AirbyteStreamConfiguration; -import io.airbyte.api.model.generated.DestinationSyncMode; -import io.airbyte.api.model.generated.SelectedFieldInfo; -import io.airbyte.api.model.generated.StreamDescriptor; -import io.airbyte.api.model.generated.SyncMode; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.text.Names; -import io.airbyte.config.FieldSelectionData; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.validation.json.JsonValidationException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Convert classes between io.airbyte.protocol.models and io.airbyte.api.model.generated - */ -public class CatalogConverter { - - private static final Logger LOGGER = LoggerFactory.getLogger(CatalogConverter.class); - - private static io.airbyte.api.model.generated.AirbyteStream toApi(final io.airbyte.protocol.models.AirbyteStream stream) { - return new io.airbyte.api.model.generated.AirbyteStream() - .name(stream.getName()) - .jsonSchema(stream.getJsonSchema()) - .supportedSyncModes(Enums.convertListTo(stream.getSupportedSyncModes(), io.airbyte.api.model.generated.SyncMode.class)) - .sourceDefinedCursor(stream.getSourceDefinedCursor()) - .defaultCursorField(stream.getDefaultCursorField()) - .sourceDefinedPrimaryKey(stream.getSourceDefinedPrimaryKey()) - .namespace(stream.getNamespace()); - } - - @SuppressWarnings("PMD.AvoidLiteralsInIfCondition") - private static io.airbyte.protocol.models.AirbyteStream toConfiguredProtocol(final AirbyteStream stream, AirbyteStreamConfiguration config) - throws JsonValidationException { - if (config.getFieldSelectionEnabled() != null && config.getFieldSelectionEnabled()) { - // Validate the selected field paths. - if (config.getSelectedFields() == null) { - throw new JsonValidationException("Requested field selection but no selected fields provided"); - } - final JsonNode properties = stream.getJsonSchema().findValue("properties"); - if (properties == null || !properties.isObject()) { - throw new JsonValidationException("Requested field selection but no properties node found"); - } - for (final var selectedFieldInfo : config.getSelectedFields()) { - if (selectedFieldInfo.getFieldPath() == null || selectedFieldInfo.getFieldPath().isEmpty()) { - throw new JsonValidationException("Selected field path cannot be empty"); - } - if (selectedFieldInfo.getFieldPath().size() > 1) { - // TODO(mfsiega-airbyte): support nested fields. - throw new UnsupportedOperationException("Nested field selection not supported"); - } - } - // Only include the selected fields. - // NOTE: we verified above that each selected field has at least one element in the field path. - final Set selectedFieldNames = - config.getSelectedFields().stream().map((field) -> field.getFieldPath().get(0)).collect(Collectors.toSet()); - // TODO(mfsiega-airbyte): we only check the top level of the cursor/primary key fields because we - // don't support filtering nested fields yet. - if (config.getSyncMode().equals(SyncMode.INCREMENTAL) // INCREMENTAL sync mode, AND - && !config.getCursorField().isEmpty() // There is a cursor configured, AND - && !selectedFieldNames.contains(config.getCursorField().get(0))) { // The cursor isn't in the selected fields. - throw new JsonValidationException("Cursor field cannot be de-selected in INCREMENTAL syncs"); - } - if (config.getDestinationSyncMode().equals(DestinationSyncMode.APPEND_DEDUP)) { - for (final List primaryKeyComponent : config.getPrimaryKey()) { - if (!selectedFieldNames.contains(primaryKeyComponent.get(0))) { - throw new JsonValidationException("Primary key field cannot be de-selected in DEDUP mode"); - } - } - } - for (final String selectedFieldName : selectedFieldNames) { - if (!properties.has(selectedFieldName)) { - throw new JsonValidationException(String.format("Requested selected field %s not found in JSON schema", selectedFieldName)); - } - } - ((ObjectNode) properties).retain(selectedFieldNames); - } - return new io.airbyte.protocol.models.AirbyteStream() - .withName(stream.getName()) - .withJsonSchema(stream.getJsonSchema()) - .withSupportedSyncModes(Enums.convertListTo(stream.getSupportedSyncModes(), io.airbyte.protocol.models.SyncMode.class)) - .withSourceDefinedCursor(stream.getSourceDefinedCursor()) - .withDefaultCursorField(stream.getDefaultCursorField()) - .withSourceDefinedPrimaryKey(Optional.ofNullable(stream.getSourceDefinedPrimaryKey()).orElse(Collections.emptyList())) - .withNamespace(stream.getNamespace()); - } - - public static io.airbyte.api.model.generated.AirbyteCatalog toApi(final io.airbyte.protocol.models.AirbyteCatalog catalog, - StandardSourceDefinition sourceDefinition) { - List suggestedStreams = new ArrayList<>(); - Boolean suggestingStreams; - - // There are occasions in tests where we have not seeded the sourceDefinition fully. This is to - // prevent those tests from failing - if (sourceDefinition != null) { - suggestingStreams = sourceDefinition.getSuggestedStreams() != null; - if (suggestingStreams) { - suggestedStreams.addAll(sourceDefinition.getSuggestedStreams().getStreams()); - } - } else { - suggestingStreams = false; - } - - return new io.airbyte.api.model.generated.AirbyteCatalog() - .streams(catalog.getStreams() - .stream() - .map(CatalogConverter::toApi) - .map(s -> new io.airbyte.api.model.generated.AirbyteStreamAndConfiguration() - .stream(s) - .config(generateDefaultConfiguration(s, suggestingStreams, suggestedStreams))) - .collect(Collectors.toList())); - } - - private static io.airbyte.api.model.generated.AirbyteStreamConfiguration generateDefaultConfiguration(final io.airbyte.api.model.generated.AirbyteStream stream, - Boolean suggestingStreams, - List suggestedStreams) { - final io.airbyte.api.model.generated.AirbyteStreamConfiguration result = new io.airbyte.api.model.generated.AirbyteStreamConfiguration() - .aliasName(Names.toAlphanumericAndUnderscore(stream.getName())) - .cursorField(stream.getDefaultCursorField()) - .destinationSyncMode(io.airbyte.api.model.generated.DestinationSyncMode.APPEND) - .primaryKey(stream.getSourceDefinedPrimaryKey()) - .selected(!suggestingStreams) - .suggested(true); - - if (suggestingStreams) { - if (suggestedStreams.contains(stream.getName())) { - result.setSelected(true); - } else { - result.setSuggested(false); - } - } - - if (stream.getSupportedSyncModes().size() > 0) { - result.setSyncMode(stream.getSupportedSyncModes().get(0)); - } else { - result.setSyncMode(io.airbyte.api.model.generated.SyncMode.INCREMENTAL); - } - - return result; - } - - public static io.airbyte.api.model.generated.AirbyteCatalog toApi(final ConfiguredAirbyteCatalog catalog, FieldSelectionData fieldSelectionData) { - final List streams = catalog.getStreams() - .stream() - .map(configuredStream -> { - final var streamDescriptor = new StreamDescriptor() - .name(configuredStream.getStream().getName()) - .namespace(configuredStream.getStream().getNamespace()); - final io.airbyte.api.model.generated.AirbyteStreamConfiguration configuration = - new io.airbyte.api.model.generated.AirbyteStreamConfiguration() - .syncMode(Enums.convertTo(configuredStream.getSyncMode(), io.airbyte.api.model.generated.SyncMode.class)) - .cursorField(configuredStream.getCursorField()) - .destinationSyncMode( - Enums.convertTo(configuredStream.getDestinationSyncMode(), io.airbyte.api.model.generated.DestinationSyncMode.class)) - .primaryKey(configuredStream.getPrimaryKey()) - .aliasName(Names.toAlphanumericAndUnderscore(configuredStream.getStream().getName())) - .selected(true) - .fieldSelectionEnabled(getStreamHasFieldSelectionEnabled(fieldSelectionData, streamDescriptor)); - if (configuration.getFieldSelectionEnabled()) { - final List selectedColumns = new ArrayList<>(); - // TODO(mfsiega-airbyte): support nested fields here. - configuredStream.getStream().getJsonSchema().findValue("properties").fieldNames().forEachRemaining((name) -> selectedColumns.add(name)); - configuration.setSelectedFields( - selectedColumns.stream().map((fieldName) -> new SelectedFieldInfo().addFieldPathItem(fieldName)).collect(Collectors.toList())); - } - return new io.airbyte.api.model.generated.AirbyteStreamAndConfiguration() - .stream(toApi(configuredStream.getStream())) - .config(configuration); - }) - .collect(Collectors.toList()); - return new io.airbyte.api.model.generated.AirbyteCatalog().streams(streams); - } - - private static Boolean getStreamHasFieldSelectionEnabled(FieldSelectionData fieldSelectionData, StreamDescriptor streamDescriptor) { - if (fieldSelectionData == null - || fieldSelectionData.getAdditionalProperties().get(streamDescriptorToStringForFieldSelection(streamDescriptor)) == null) { - return false; - } - - return fieldSelectionData.getAdditionalProperties().get(streamDescriptorToStringForFieldSelection(streamDescriptor)); - } - - /** - * Converts the API catalog model into a protocol catalog. Note: returns all streams, regardless of - * selected status. See - * {@link CatalogConverter#toConfiguredProtocol(AirbyteStream, AirbyteStreamConfiguration)} for - * context. - * - * @param catalog api catalog - * @return protocol catalog - */ - public static io.airbyte.protocol.models.ConfiguredAirbyteCatalog toProtocolKeepAllStreams( - final io.airbyte.api.model.generated.AirbyteCatalog catalog) - throws JsonValidationException { - final AirbyteCatalog clone = Jsons.clone(catalog); - clone.getStreams().forEach(stream -> stream.getConfig().setSelected(true)); - return toConfiguredProtocol(clone); - } - - /** - * To convert AirbyteCatalog from APIs to model. This is to differentiate between - * toConfiguredProtocol as the other one converts to ConfiguredAirbyteCatalog object instead. - */ - public static io.airbyte.protocol.models.AirbyteCatalog toProtocol( - final io.airbyte.api.model.generated.AirbyteCatalog catalog) - throws JsonValidationException { - final ArrayList errors = new ArrayList<>(); - - io.airbyte.protocol.models.AirbyteCatalog protoCatalog = - new io.airbyte.protocol.models.AirbyteCatalog(); - var airbyteStream = catalog.getStreams().stream().map(stream -> { - try { - return toConfiguredProtocol(stream.getStream(), stream.getConfig()); - } catch (JsonValidationException e) { - LOGGER.error("Error parsing catalog: {}", e); - errors.add(e); - return null; - } - }).collect(Collectors.toList()); - - if (!errors.isEmpty()) { - throw errors.get(0); - } - protoCatalog.withStreams(airbyteStream); - return protoCatalog; - } - - /** - * Converts the API catalog model into a protocol catalog. Note: only streams marked as selected - * will be returned. This is included in this converter as the API model always carries all the - * streams it has access to and then marks the ones that should not be used as not selected, while - * the protocol version just uses the presence of the streams as evidence that it should be - * included. - * - * @param catalog api catalog - * @return protocol catalog - */ - public static io.airbyte.protocol.models.ConfiguredAirbyteCatalog toConfiguredProtocol(final io.airbyte.api.model.generated.AirbyteCatalog catalog) - throws JsonValidationException { - final ArrayList errors = new ArrayList<>(); - final List streams = catalog.getStreams() - .stream() - .filter(s -> s.getConfig().getSelected()) - .map(s -> { - try { - return new io.airbyte.protocol.models.ConfiguredAirbyteStream() - .withStream(toConfiguredProtocol(s.getStream(), s.getConfig())) - .withSyncMode(Enums.convertTo(s.getConfig().getSyncMode(), io.airbyte.protocol.models.SyncMode.class)) - .withCursorField(s.getConfig().getCursorField()) - .withDestinationSyncMode(Enums.convertTo(s.getConfig().getDestinationSyncMode(), - io.airbyte.protocol.models.DestinationSyncMode.class)) - .withPrimaryKey(Optional.ofNullable(s.getConfig().getPrimaryKey()).orElse(Collections.emptyList())); - } catch (JsonValidationException e) { - LOGGER.error("Error parsing catalog: {}", e); - errors.add(e); - return null; - } - }) - .collect(Collectors.toList()); - if (!errors.isEmpty()) { - throw errors.get(0); - } - return new io.airbyte.protocol.models.ConfiguredAirbyteCatalog() - .withStreams(streams); - } - - /** - * Generate the map from StreamDescriptor to indicator of whether field selection is enabled for - * that stream. - * - * @param syncCatalog the catalog - * @return the map as a FieldSelectionData object - */ - public static FieldSelectionData getFieldSelectionData(final AirbyteCatalog syncCatalog) { - if (syncCatalog == null) { - return null; - } - final var fieldSelectionData = new FieldSelectionData(); - for (final AirbyteStreamAndConfiguration streamAndConfig : syncCatalog.getStreams()) { - final var streamDescriptor = new StreamDescriptor() - .name(streamAndConfig.getStream().getName()) - .namespace(streamAndConfig.getStream().getNamespace()); - final boolean fieldSelectionEnabled = - streamAndConfig.getConfig().getFieldSelectionEnabled() == null ? false : streamAndConfig.getConfig().getFieldSelectionEnabled(); - fieldSelectionData.setAdditionalProperty(streamDescriptorToStringForFieldSelection(streamDescriptor), fieldSelectionEnabled); - } - return fieldSelectionData; - } - - // Return a string representation of a stream descriptor that's convenient to use as a key for the - // field selection data. - private static String streamDescriptorToStringForFieldSelection(final StreamDescriptor streamDescriptor) { - return String.format("%s/%s", streamDescriptor.getNamespace(), streamDescriptor.getName()); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionMatcher.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionMatcher.java deleted file mode 100644 index 1360536e36bb9..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionMatcher.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionSearch; -import org.apache.logging.log4j.util.Strings; - -public class ConnectionMatcher implements Matchable { - - private final ConnectionSearch search; - - public ConnectionMatcher(final ConnectionSearch search) { - this.search = search; - } - - @Override - public ConnectionRead match(final ConnectionRead query) { - if (search == null) { - return query; - } - - final ConnectionRead fromSearch = new ConnectionRead(); - fromSearch.connectionId(search.getConnectionId() == null ? query.getConnectionId() : search.getConnectionId()); - fromSearch.destinationId(search.getDestinationId() == null ? query.getDestinationId() : search.getDestinationId()); - fromSearch.name(Strings.isBlank(search.getName()) ? query.getName() : search.getName()); - fromSearch.namespaceFormat(Strings.isBlank(search.getNamespaceFormat()) || "null".equals(search.getNamespaceFormat()) - ? query.getNamespaceFormat() - : search.getNamespaceFormat()); - fromSearch.namespaceDefinition( - search.getNamespaceDefinition() == null ? query.getNamespaceDefinition() : search.getNamespaceDefinition()); - fromSearch.prefix(Strings.isBlank(search.getPrefix()) ? query.getPrefix() : search.getPrefix()); - fromSearch.schedule(search.getSchedule() == null ? query.getSchedule() : search.getSchedule()); - fromSearch.scheduleType(search.getScheduleType() == null ? query.getScheduleType() : search.getScheduleType()); - fromSearch.scheduleData(search.getScheduleData() == null ? query.getScheduleData() : search.getScheduleData()); - fromSearch.sourceId(search.getSourceId() == null ? query.getSourceId() : search.getSourceId()); - fromSearch.status(search.getStatus() == null ? query.getStatus() : search.getStatus()); - - // these properties are not enabled in the search - fromSearch.resourceRequirements(query.getResourceRequirements()); - fromSearch.syncCatalog(query.getSyncCatalog()); - fromSearch.operationIds(query.getOperationIds()); - fromSearch.sourceCatalogId(query.getSourceCatalogId()); - fromSearch.geography(query.getGeography()); - fromSearch.breakingChange(query.getBreakingChange()); - - return fromSearch; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionScheduleHelper.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionScheduleHelper.java deleted file mode 100644 index 23c0fda9d4f70..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/ConnectionScheduleHelper.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -import io.airbyte.api.model.generated.ConnectionScheduleData; -import io.airbyte.api.model.generated.ConnectionScheduleType; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.config.BasicSchedule; -import io.airbyte.config.Cron; -import io.airbyte.config.Schedule; -import io.airbyte.config.ScheduleData; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.ScheduleType; -import io.airbyte.validation.json.JsonValidationException; -import java.text.ParseException; -import java.util.TimeZone; -import org.joda.time.DateTimeZone; -import org.quartz.CronExpression; - -/** - * Helper class to handle connection schedules, including validation and translating between API and - * config. - */ -public class ConnectionScheduleHelper { - - public static void populateSyncFromScheduleTypeAndData(final StandardSync standardSync, - final ConnectionScheduleType scheduleType, - final ConnectionScheduleData scheduleData) - throws JsonValidationException { - if (scheduleType != ConnectionScheduleType.MANUAL && scheduleData == null) { - throw new JsonValidationException("schedule data must be populated if schedule type is populated"); - } - switch (scheduleType) { - // NOTE: the `manual` column is marked required, so we populate it until it's removed. - case MANUAL -> { - standardSync.withScheduleType(ScheduleType.MANUAL).withScheduleData(null).withManual(true); - - // explicitly null out the legacy `schedule` column until it's removed. - standardSync.withSchedule(null); - } - case BASIC -> { - if (scheduleData.getBasicSchedule() == null) { - throw new JsonValidationException("if schedule type is basic, then scheduleData.basic must be populated"); - } - standardSync - .withScheduleType(ScheduleType.BASIC_SCHEDULE) - .withScheduleData(new ScheduleData().withBasicSchedule( - new BasicSchedule().withTimeUnit(ApiPojoConverters.toBasicScheduleTimeUnit(scheduleData.getBasicSchedule().getTimeUnit())) - .withUnits(scheduleData.getBasicSchedule().getUnits()))) - .withManual(false); - // Populate the legacy format for now as well, since some places still expect it to exist. - // TODO(https://github.com/airbytehq/airbyte/issues/11432): remove. - final Schedule schedule = new Schedule() - .withTimeUnit(ApiPojoConverters.toLegacyScheduleTimeUnit(scheduleData.getBasicSchedule().getTimeUnit())) - .withUnits(scheduleData.getBasicSchedule().getUnits()); - standardSync - .withManual(false) - .withSchedule(schedule); - } - case CRON -> { - if (scheduleData.getCron() == null) { - throw new JsonValidationException("if schedule type is cron, then scheduleData.cron must be populated"); - } - // Validate that this is a valid cron expression and timezone. - final String cronExpression = scheduleData.getCron().getCronExpression(); - final String cronTimeZone = scheduleData.getCron().getCronTimeZone(); - if (cronExpression == null || cronTimeZone == null) { - throw new JsonValidationException("Cron expression and timezone are required"); - } - if (cronTimeZone.toLowerCase().startsWith("etc")) { - throw new JsonValidationException("Etc/ timezones are unsupported"); - } - try { - final TimeZone timeZone = DateTimeZone.forID(cronTimeZone).toTimeZone(); - final CronExpression parsedCronExpression = new CronExpression(cronExpression); - parsedCronExpression.setTimeZone(timeZone); - } catch (ParseException e) { - throw (JsonValidationException) new JsonValidationException("invalid cron expression").initCause(e); - } catch (IllegalArgumentException e) { - throw (JsonValidationException) new JsonValidationException("invalid cron timezone").initCause(e); - } - standardSync - .withScheduleType(ScheduleType.CRON) - .withScheduleData(new ScheduleData().withCron(new Cron() - .withCronExpression(cronExpression) - .withCronTimeZone(cronTimeZone))) - .withManual(false); - - // explicitly null out the legacy `schedule` column until it's removed. - standardSync.withSchedule(null); - } - } - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/DestinationMatcher.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/DestinationMatcher.java deleted file mode 100644 index 03c8f9d589251..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/DestinationMatcher.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationSearch; -import org.apache.logging.log4j.util.Strings; - -public class DestinationMatcher implements Matchable { - - private final DestinationSearch search; - - public DestinationMatcher(final DestinationSearch search) { - this.search = search; - } - - @Override - public DestinationRead match(final DestinationRead query) { - if (search == null) { - return query; - } - - final DestinationRead fromSearch = new DestinationRead(); - fromSearch.name(Strings.isBlank(search.getName()) ? query.getName() : search.getName()); - fromSearch.destinationDefinitionId(search.getDestinationDefinitionId() == null ? query.getDestinationDefinitionId() - : search.getDestinationDefinitionId()); - fromSearch - .destinationId(search.getDestinationId() == null ? query.getDestinationId() : search.getDestinationId()); - fromSearch.destinationName( - Strings.isBlank(search.getDestinationName()) ? query.getDestinationName() : search.getDestinationName()); - fromSearch.workspaceId(search.getWorkspaceId() == null ? query.getWorkspaceId() : search.getWorkspaceId()); - if (search.getConnectionConfiguration() == null) { - fromSearch.connectionConfiguration(query.getConnectionConfiguration()); - } else if (query.getConnectionConfiguration() == null) { - fromSearch.connectionConfiguration(search.getConnectionConfiguration()); - } else { - final JsonNode connectionConfiguration = search.getConnectionConfiguration(); - query.getConnectionConfiguration().fieldNames() - .forEachRemaining(field -> { - if (!connectionConfiguration.has(field) && connectionConfiguration instanceof ObjectNode) { - ((ObjectNode) connectionConfiguration).set(field, query.getConnectionConfiguration().get(field)); - } - }); - fromSearch.connectionConfiguration(connectionConfiguration); - } - - return fromSearch; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/Matchable.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/Matchable.java deleted file mode 100644 index 671c23e8480c2..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/Matchable.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -@FunctionalInterface -interface Matchable { - - K match(K k); - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/OAuthPathExtractor.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/OAuthPathExtractor.java deleted file mode 100644 index 18624ac1ff778..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/OAuthPathExtractor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -import com.fasterxml.jackson.databind.JsonNode; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class OAuthPathExtractor { - - private static final String PROPERTIES = "properties"; - private static final String PATH_IN_CONNECTOR_CONFIG = "path_in_connector_config"; - - public static Map> extractOauthConfigurationPaths(final JsonNode configuration) { - - if (configuration != null && configuration.has(PROPERTIES) && configuration.get(PROPERTIES).isObject()) { - final Map> result = new HashMap<>(); - - configuration.get(PROPERTIES).fields().forEachRemaining(entry -> { - final JsonNode value = entry.getValue(); - if (value.isObject() && value.has(PATH_IN_CONNECTOR_CONFIG) && value.get(PATH_IN_CONNECTOR_CONFIG).isArray()) { - final List path = new ArrayList<>(); - for (final JsonNode pathPart : value.get(PATH_IN_CONNECTOR_CONFIG)) { - path.add(pathPart.textValue()); - } - result.put(entry.getKey(), path); - } - }); - - return result; - } else { - return new HashMap<>(); - } - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/SourceMatcher.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/SourceMatcher.java deleted file mode 100644 index 6f9f120a83257..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/handlers/helpers/SourceMatcher.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helpers; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceSearch; -import org.apache.logging.log4j.util.Strings; - -public class SourceMatcher implements Matchable { - - private final SourceSearch search; - - public SourceMatcher(final SourceSearch search) { - this.search = search; - } - - @Override - public SourceRead match(final SourceRead query) { - if (search == null) { - return query; - } - - final SourceRead fromSearch = new SourceRead(); - fromSearch.name(Strings.isBlank(search.getName()) ? query.getName() : search.getName()); - fromSearch.sourceDefinitionId(search.getSourceDefinitionId() == null ? query.getSourceDefinitionId() : search.getSourceDefinitionId()); - fromSearch.sourceId(search.getSourceId() == null ? query.getSourceId() : search.getSourceId()); - fromSearch.sourceName(Strings.isBlank(search.getSourceName()) ? query.getSourceName() : search.getSourceName()); - fromSearch.workspaceId(search.getWorkspaceId() == null ? query.getWorkspaceId() : search.getWorkspaceId()); - if (search.getConnectionConfiguration() == null) { - fromSearch.connectionConfiguration(query.getConnectionConfiguration()); - } else if (query.getConnectionConfiguration() == null) { - fromSearch.connectionConfiguration(search.getConnectionConfiguration()); - } else { - final JsonNode connectionConfiguration = search.getConnectionConfiguration(); - query.getConnectionConfiguration().fieldNames() - .forEachRemaining(field -> { - if (!connectionConfiguration.has(field) && connectionConfiguration instanceof ObjectNode) { - ((ObjectNode) connectionConfiguration).set(field, query.getConnectionConfiguration().get(field)); - } - }); - fromSearch.connectionConfiguration(connectionConfiguration); - } - - return fromSearch; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClient.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClient.java deleted file mode 100644 index f6a69bbd35c71..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClient.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Charsets; -import com.google.common.hash.HashFunction; -import com.google.common.hash.Hashing; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.lang.Exceptions; -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.temporal.TemporalJobType; -import io.airbyte.commons.temporal.TemporalResponse; -import io.airbyte.commons.temporal.scheduling.RouterService; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorType; -import io.airbyte.config.ConnectorJobOutput; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.JobCheckConnectionConfig; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.JobDiscoverCatalogConfig; -import io.airbyte.config.JobGetSpecConfig; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardCheckConnectionOutput; -import io.airbyte.persistence.job.errorreporter.ConnectorJobReportingContext; -import io.airbyte.persistence.job.errorreporter.JobErrorReporter; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.persistence.job.tracker.JobTracker; -import io.airbyte.persistence.job.tracker.JobTracker.JobState; -import io.airbyte.protocol.models.ConnectorSpecification; -import java.io.IOException; -import java.time.Instant; -import java.util.Optional; -import java.util.UUID; -import java.util.function.Function; -import java.util.function.Supplier; -import javax.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DefaultSynchronousSchedulerClient implements SynchronousSchedulerClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSynchronousSchedulerClient.class); - - private static final HashFunction HASH_FUNCTION = Hashing.md5(); - - private final TemporalClient temporalClient; - private final JobTracker jobTracker; - private final JobErrorReporter jobErrorReporter; - private final OAuthConfigSupplier oAuthConfigSupplier; - - private final RouterService routerService; - - public DefaultSynchronousSchedulerClient(final TemporalClient temporalClient, - final JobTracker jobTracker, - final JobErrorReporter jobErrorReporter, - final OAuthConfigSupplier oAuthConfigSupplier, - final RouterService routerService) { - this.temporalClient = temporalClient; - this.jobTracker = jobTracker; - this.jobErrorReporter = jobErrorReporter; - this.oAuthConfigSupplier = oAuthConfigSupplier; - this.routerService = routerService; - } - - @Override - public SynchronousResponse createSourceCheckConnectionJob(final SourceConnection source, - final String dockerImage, - final Version protocolVersion, - final boolean isCustomConnector) - throws IOException { - final JsonNode sourceConfiguration = oAuthConfigSupplier.injectSourceOAuthParameters( - source.getSourceDefinitionId(), - source.getWorkspaceId(), - source.getConfiguration()); - final JobCheckConnectionConfig jobCheckConnectionConfig = new JobCheckConnectionConfig() - .withActorType(ActorType.SOURCE) - .withActorId(source.getSourceId()) - .withConnectionConfiguration(sourceConfiguration) - .withDockerImage(dockerImage) - .withProtocolVersion(protocolVersion) - .withIsCustomConnector(isCustomConnector); - - final UUID jobId = UUID.randomUUID(); - final ConnectorJobReportingContext jobReportingContext = new ConnectorJobReportingContext(jobId, dockerImage); - String taskQueue = routerService.getTaskQueueForWorkspace(source.getWorkspaceId(), TemporalJobType.CHECK_CONNECTION); - - return execute( - ConfigType.CHECK_CONNECTION_SOURCE, - jobReportingContext, - source.getSourceDefinitionId(), - () -> temporalClient.submitCheckConnection(UUID.randomUUID(), 0, taskQueue, jobCheckConnectionConfig), - ConnectorJobOutput::getCheckConnection, - source.getWorkspaceId()); - } - - @Override - public SynchronousResponse createDestinationCheckConnectionJob(final DestinationConnection destination, - final String dockerImage, - final Version protocolVersion, - final boolean isCustomConnector) - throws IOException { - final JsonNode destinationConfiguration = oAuthConfigSupplier.injectDestinationOAuthParameters( - destination.getDestinationDefinitionId(), - destination.getWorkspaceId(), - destination.getConfiguration()); - final JobCheckConnectionConfig jobCheckConnectionConfig = new JobCheckConnectionConfig() - .withActorType(ActorType.DESTINATION) - .withActorId(destination.getDestinationId()) - .withConnectionConfiguration(destinationConfiguration) - .withDockerImage(dockerImage) - .withProtocolVersion(protocolVersion) - .withIsCustomConnector(isCustomConnector); - - final UUID jobId = UUID.randomUUID(); - final ConnectorJobReportingContext jobReportingContext = new ConnectorJobReportingContext(jobId, dockerImage); - String taskQueue = routerService.getTaskQueueForWorkspace(destination.getWorkspaceId(), TemporalJobType.CHECK_CONNECTION); - - return execute( - ConfigType.CHECK_CONNECTION_DESTINATION, - jobReportingContext, - destination.getDestinationDefinitionId(), - () -> temporalClient.submitCheckConnection(jobId, 0, taskQueue, jobCheckConnectionConfig), - ConnectorJobOutput::getCheckConnection, - destination.getWorkspaceId()); - } - - @Override - public SynchronousResponse createDiscoverSchemaJob(final SourceConnection source, - final String dockerImage, - final String connectorVersion, - final Version protocolVersion, - final boolean isCustomConnector) - throws IOException { - final JsonNode sourceConfiguration = oAuthConfigSupplier.injectSourceOAuthParameters( - source.getSourceDefinitionId(), - source.getWorkspaceId(), - source.getConfiguration()); - final JobDiscoverCatalogConfig jobDiscoverCatalogConfig = new JobDiscoverCatalogConfig() - .withConnectionConfiguration(sourceConfiguration) - .withDockerImage(dockerImage) - .withProtocolVersion(protocolVersion) - .withSourceId(source.getSourceId().toString()) - .withConfigHash(HASH_FUNCTION.hashBytes(Jsons.serialize(source.getConfiguration()).getBytes( - Charsets.UTF_8)).toString()) - .withConnectorVersion(connectorVersion) - .withIsCustomConnector(isCustomConnector); - - final UUID jobId = UUID.randomUUID(); - final ConnectorJobReportingContext jobReportingContext = new ConnectorJobReportingContext(jobId, dockerImage); - - String taskQueue = routerService.getTaskQueueForWorkspace(source.getWorkspaceId(), TemporalJobType.DISCOVER_SCHEMA); - - return execute( - ConfigType.DISCOVER_SCHEMA, - jobReportingContext, - source.getSourceDefinitionId(), - () -> temporalClient.submitDiscoverSchema(jobId, 0, taskQueue, jobDiscoverCatalogConfig), - ConnectorJobOutput::getDiscoverCatalogId, - source.getWorkspaceId()); - } - - @Override - public SynchronousResponse createGetSpecJob(final String dockerImage, final boolean isCustomConnector) throws IOException { - final JobGetSpecConfig jobSpecConfig = new JobGetSpecConfig().withDockerImage(dockerImage).withIsCustomConnector(isCustomConnector); - - final UUID jobId = UUID.randomUUID(); - final ConnectorJobReportingContext jobReportingContext = new ConnectorJobReportingContext(jobId, dockerImage); - - return execute( - ConfigType.GET_SPEC, - jobReportingContext, - null, - () -> temporalClient.submitGetSpec(jobId, 0, jobSpecConfig), - ConnectorJobOutput::getSpec, - null); - } - - @VisibleForTesting - SynchronousResponse execute(final ConfigType configType, - final ConnectorJobReportingContext jobContext, - @Nullable final UUID connectorDefinitionId, - final Supplier> executor, - final Function outputMapper, - final UUID workspaceId) { - final long createdAt = Instant.now().toEpochMilli(); - final UUID jobId = jobContext.jobId(); - try { - track(jobId, configType, connectorDefinitionId, workspaceId, JobState.STARTED, null); - final TemporalResponse temporalResponse = executor.get(); - final Optional jobOutput = temporalResponse.getOutput(); - final T mappedOutput = jobOutput.map(outputMapper).orElse(null); - final JobState outputState = temporalResponse.getMetadata().isSucceeded() ? JobState.SUCCEEDED : JobState.FAILED; - - track(jobId, configType, connectorDefinitionId, workspaceId, outputState, mappedOutput); - - if (outputState == JobState.FAILED && jobOutput.isPresent()) { - reportError(configType, jobContext, jobOutput.get(), connectorDefinitionId, workspaceId); - } - - final long endedAt = Instant.now().toEpochMilli(); - return SynchronousResponse.fromTemporalResponse( - temporalResponse, - jobOutput.orElse(null), - mappedOutput, - jobId, - configType, - connectorDefinitionId, - createdAt, - endedAt); - } catch (final RuntimeException e) { - track(jobId, configType, connectorDefinitionId, workspaceId, JobState.FAILED, null); - throw e; - } - } - - /** - * @param connectorDefinitionId either source or destination definition id - */ - private void track(final UUID jobId, - final ConfigType configType, - final UUID connectorDefinitionId, - final UUID workspaceId, - final JobState jobState, - final T value) { - switch (configType) { - case CHECK_CONNECTION_SOURCE -> jobTracker.trackCheckConnectionSource( - jobId, - connectorDefinitionId, - workspaceId, - jobState, - (StandardCheckConnectionOutput) value); - case CHECK_CONNECTION_DESTINATION -> jobTracker.trackCheckConnectionDestination( - jobId, - connectorDefinitionId, - workspaceId, - jobState, - (StandardCheckConnectionOutput) value); - case DISCOVER_SCHEMA -> jobTracker.trackDiscover(jobId, connectorDefinitionId, workspaceId, jobState); - case GET_SPEC -> { - // skip tracking for get spec to avoid noise. - } - default -> throw new IllegalArgumentException( - String.format("Jobs of type %s cannot be processed here. They should be consumed in the JobSubmitter.", configType)); - } - - } - - private void reportError(final ConfigType configType, - final ConnectorJobReportingContext jobContext, - final T jobOutput, - final UUID connectorDefinitionId, - final UUID workspaceId) { - Exceptions.swallow(() -> { - switch (configType) { - case CHECK_CONNECTION_SOURCE -> jobErrorReporter.reportSourceCheckJobFailure( - connectorDefinitionId, - workspaceId, - ((ConnectorJobOutput) jobOutput).getFailureReason(), - jobContext); - case CHECK_CONNECTION_DESTINATION -> jobErrorReporter.reportDestinationCheckJobFailure( - connectorDefinitionId, - workspaceId, - ((ConnectorJobOutput) jobOutput).getFailureReason(), - jobContext); - case DISCOVER_SCHEMA -> jobErrorReporter.reportDiscoverJobFailure( - connectorDefinitionId, - workspaceId, - ((ConnectorJobOutput) jobOutput).getFailureReason(), - jobContext); - case GET_SPEC -> jobErrorReporter.reportSpecJobFailure( - ((ConnectorJobOutput) jobOutput).getFailureReason(), - jobContext); - default -> LOGGER.error("Tried to report job failure for type {}, but this job type is not supported", configType); - } - }); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/EventRunner.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/EventRunner.java deleted file mode 100644 index 59ce6f4394f16..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/EventRunner.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import io.airbyte.commons.temporal.TemporalClient.ManualOperationResult; -import io.airbyte.protocol.models.StreamDescriptor; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -public interface EventRunner { - - void createConnectionManagerWorkflow(final UUID connectionId); - - ManualOperationResult startNewManualSync(final UUID connectionId); - - ManualOperationResult startNewCancellation(final UUID connectionId); - - ManualOperationResult resetConnection(final UUID connectionId, final List streamsToReset, final boolean runSyncImmediately); - - void forceDeleteConnection(final UUID connectionId); - - // TODO: Delete - @Deprecated(forRemoval = true) - void migrateSyncIfNeeded(final Set connectionIds); - - void update(final UUID connectionId); - - void sendSchemaChangeNotification(final UUID connectionId, final String url); - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousJobMetadata.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousJobMetadata.java deleted file mode 100644 index 46b9658c3a951..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousJobMetadata.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import io.airbyte.commons.temporal.JobMetadata; -import io.airbyte.config.JobConfig.ConfigType; -import java.nio.file.Path; -import java.time.Instant; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; - -public class SynchronousJobMetadata { - - private final UUID id; - private final ConfigType configType; - private final UUID configId; - - private final long createdAt; - private final long endedAt; - private final boolean succeeded; - private final boolean connectorConfigurationUpdated; - - private final Path logPath; - - public static SynchronousJobMetadata fromJobMetadata(final JobMetadata jobMetadata, - final UUID id, - final ConfigType configType, - final UUID configId, - final boolean connectorConfigurationUpdated, - final long createdAt, - final long endedAt) { - return new SynchronousJobMetadata( - id, - configType, - configId, - createdAt, - endedAt, - jobMetadata.isSucceeded(), - connectorConfigurationUpdated, - jobMetadata.getLogPath()); - } - - public SynchronousJobMetadata(final UUID id, - final ConfigType configType, - final UUID configId, - final long createdAt, - final long endedAt, - final boolean succeeded, - final boolean connectorConfigurationUpdated, - final Path logPath) { - this.id = id; - this.configType = configType; - this.configId = configId; - this.createdAt = createdAt; - this.endedAt = endedAt; - this.succeeded = succeeded; - this.connectorConfigurationUpdated = connectorConfigurationUpdated; - this.logPath = logPath; - } - - public UUID getId() { - return id; - } - - public ConfigType getConfigType() { - return configType; - } - - public Optional getConfigId() { - return Optional.ofNullable(configId); - } - - public long getCreatedAt() { - return createdAt; - } - - public long getEndedAt() { - return endedAt; - } - - public boolean isSucceeded() { - return succeeded; - } - - public boolean isConnectorConfigurationUpdated() { - return connectorConfigurationUpdated; - } - - public Path getLogPath() { - return logPath; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final SynchronousJobMetadata that = (SynchronousJobMetadata) o; - return createdAt == that.createdAt && endedAt == that.endedAt && succeeded == that.succeeded - && connectorConfigurationUpdated == that.connectorConfigurationUpdated && Objects.equals(id, that.id) - && configType == that.configType && Objects.equals(configId, that.configId) && Objects.equals(logPath, that.logPath); - } - - @Override - public int hashCode() { - return Objects.hash(id, configType, configId, createdAt, endedAt, succeeded, connectorConfigurationUpdated, logPath); - } - - @Override - public String toString() { - return "SynchronousJobMetadata{" + - "id=" + id + - ", configType=" + configType + - ", configId=" + configId + - ", createdAt=" + createdAt + - ", endedAt=" + endedAt + - ", succeeded=" + succeeded + - ", connectorConfigurationUpdated=" + connectorConfigurationUpdated + - ", logPath=" + logPath + - '}'; - } - - public static SynchronousJobMetadata mock(final ConfigType configType) { - final long now = Instant.now().toEpochMilli(); - final UUID configId = null; - final boolean succeeded = true; - final boolean connectorConfigurationUpdated = false; - final Path logPath = null; - - return new SynchronousJobMetadata( - UUID.randomUUID(), - configType, - configId, - now, - now, - succeeded, - connectorConfigurationUpdated, - logPath); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousResponse.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousResponse.java deleted file mode 100644 index 38f31929ceec2..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousResponse.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import io.airbyte.commons.temporal.TemporalResponse; -import io.airbyte.config.ConnectorJobOutput; -import io.airbyte.config.JobConfig.ConfigType; -import java.util.Objects; -import java.util.UUID; -import javax.annotation.Nullable; - -public class SynchronousResponse { - - private final T output; - private final SynchronousJobMetadata metadata; - - public static SynchronousResponse error(final SynchronousJobMetadata metadata) { - return new SynchronousResponse<>(null, metadata); - } - - public static SynchronousResponse success(final T output, final SynchronousJobMetadata metadata) { - return new SynchronousResponse<>(output, metadata); - } - - public static SynchronousResponse fromTemporalResponse(final TemporalResponse temporalResponse, - @Nullable final ConnectorJobOutput jobOutput, - @Nullable final T responseOutput, - final UUID id, - final ConfigType configType, - final UUID configId, - final long createdAt, - final long endedAt) { - - final SynchronousJobMetadata metadata = SynchronousJobMetadata.fromJobMetadata( - temporalResponse.getMetadata(), - id, - configType, - configId, - jobOutput != null ? jobOutput.getConnectorConfigurationUpdated() : false, - createdAt, - endedAt); - return new SynchronousResponse<>(responseOutput, metadata); - } - - public SynchronousResponse(final T output, final SynchronousJobMetadata metadata) { - this.output = output; - this.metadata = metadata; - } - - public boolean isSuccess() { - return metadata.isSucceeded(); - } - - public T getOutput() { - return output; - } - - public SynchronousJobMetadata getMetadata() { - return metadata; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final SynchronousResponse that = (SynchronousResponse) o; - return Objects.equals(output, that.output) && Objects.equals(metadata, that.metadata); - } - - @Override - public int hashCode() { - return Objects.hash(output, metadata); - } - - @Override - public String toString() { - return "SynchronousResponse{" + - "output=" + output + - ", metadata=" + metadata + - '}'; - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousSchedulerClient.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousSchedulerClient.java deleted file mode 100644 index 7be72c1ed8b01..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/SynchronousSchedulerClient.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import io.airbyte.commons.version.Version; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardCheckConnectionOutput; -import io.airbyte.protocol.models.ConnectorSpecification; -import java.io.IOException; -import java.util.UUID; - -/** - * Exposes a way of executing short-lived jobs as RPC calls. Blocks until the job completes. No - * metadata will be stored in the Jobs table for jobs triggered via this client. - */ -public interface SynchronousSchedulerClient { - - SynchronousResponse createSourceCheckConnectionJob(SourceConnection source, - String dockerImage, - Version protocolVersion, - boolean isCustomConnector) - throws IOException; - - SynchronousResponse createDestinationCheckConnectionJob(DestinationConnection destination, - String dockerImage, - Version protocolVersion, - boolean isCustomConnector) - throws IOException; - - SynchronousResponse createDiscoverSchemaJob(SourceConnection source, - String dockerImage, - String connectorVersion, - Version protocolVersion, - boolean isCustomConnector) - throws IOException; - - SynchronousResponse createGetSpecJob(String dockerImage, boolean isCustomConnector) throws IOException; - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/TemporalEventRunner.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/TemporalEventRunner.java deleted file mode 100644 index 9e6ed0068e51a..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/scheduler/TemporalEventRunner.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.temporal.TemporalClient.ManualOperationResult; -import io.airbyte.protocol.models.StreamDescriptor; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import lombok.AllArgsConstructor; - -@AllArgsConstructor -public class TemporalEventRunner implements EventRunner { - - private final TemporalClient temporalClient; - - @Override - public void createConnectionManagerWorkflow(final UUID connectionId) { - temporalClient.submitConnectionUpdaterAsync(connectionId); - } - - @Override - public ManualOperationResult startNewManualSync(final UUID connectionId) { - return temporalClient.startNewManualSync(connectionId); - } - - @Override - public ManualOperationResult startNewCancellation(final UUID connectionId) { - return temporalClient.startNewCancellation(connectionId); - } - - @Override - public ManualOperationResult resetConnection(final UUID connectionId, - final List streamsToReset, - final boolean runSyncImmediately) { - return temporalClient.resetConnection(connectionId, streamsToReset, runSyncImmediately); - } - - @Override - public void forceDeleteConnection(final UUID connectionId) { - temporalClient.forceDeleteWorkflow(connectionId); - } - - @Override - public void migrateSyncIfNeeded(final Set connectionIds) { - temporalClient.migrateSyncIfNeeded(connectionIds); - } - - @Override - public void update(final UUID connectionId) { - temporalClient.update(connectionId); - } - - @Override - public void sendSchemaChangeNotification(final UUID connectionId, final String url) { - temporalClient.sendSchemaChangeNotification(connectionId, url); - } - -} diff --git a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/services/AirbyteGithubStore.java b/airbyte-commons-server/src/main/java/io/airbyte/commons/server/services/AirbyteGithubStore.java deleted file mode 100644 index 658b53ab629f8..0000000000000 --- a/airbyte-commons-server/src/main/java/io/airbyte/commons/server/services/AirbyteGithubStore.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.services; - -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.config.EnvConfigs; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.helpers.YamlListToStandardDefinitions; -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse.BodyHandlers; -import java.time.Duration; -import java.util.Collections; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Convenience class for retrieving files checked into the Airbyte Github repo. - */ -@SuppressWarnings("PMD.AvoidCatchingThrowable") -public class AirbyteGithubStore { - - private static final Logger LOGGER = LoggerFactory.getLogger(AirbyteGithubStore.class); - private static final EnvConfigs envConfigs = new EnvConfigs(); - private static final String GITHUB_BASE_URL = "https://raw.githubusercontent.com"; - private static final String SOURCE_DEFINITION_LIST_LOCATION_PATH = - "/airbytehq/airbyte/" + envConfigs.getGithubStoreBranch() + "/airbyte-config/init/src/main/resources/seed/source_definitions.yaml"; - private static final String DESTINATION_DEFINITION_LIST_LOCATION_PATH = - "/airbytehq/airbyte/" + envConfigs.getGithubStoreBranch() + "/airbyte-config/init/src/main/resources/seed/destination_definitions.yaml"; - private static final HttpClient httpClient = HttpClient.newHttpClient(); - - private final String baseUrl; - private final Duration timeout; - - public static AirbyteGithubStore production() { - return new AirbyteGithubStore(GITHUB_BASE_URL, Duration.ofSeconds(30)); - } - - public static AirbyteGithubStore test(final String testBaseUrl, final Duration timeout) { - return new AirbyteGithubStore(testBaseUrl, timeout); - } - - public AirbyteGithubStore(final String baseUrl, final Duration timeout) { - this.baseUrl = baseUrl; - this.timeout = timeout; - } - - public List getLatestDestinations() throws InterruptedException { - try { - return YamlListToStandardDefinitions.toStandardDestinationDefinitions(getFile(DESTINATION_DEFINITION_LIST_LOCATION_PATH)); - } catch (final Throwable e) { - LOGGER.warn( - "Unable to retrieve latest Destination list from Github. Using the list bundled with Airbyte. This warning is expected if this Airbyte cluster does not have internet access.", - e); - return Collections.emptyList(); - } - } - - public List getLatestSources() throws InterruptedException { - try { - return YamlListToStandardDefinitions.toStandardSourceDefinitions(getFile(SOURCE_DEFINITION_LIST_LOCATION_PATH)); - } catch (final Throwable e) { - LOGGER.warn( - "Unable to retrieve latest Source list from Github. Using the list bundled with Airbyte. This warning is expected if this Airbyte cluster does not have internet access.", - e); - return Collections.emptyList(); - } - } - - @VisibleForTesting - String getFile(final String filePathWithSlashPrefix) throws IOException, InterruptedException { - final var request = HttpRequest - .newBuilder(URI.create(baseUrl + filePathWithSlashPrefix)) - .timeout(timeout) - .header("accept", "*/*") // accept any file type - .build(); - final var resp = httpClient.send(request, BodyHandlers.ofString()); - final Boolean isErrorResponse = resp.statusCode() / 100 != 2; - if (isErrorResponse) { - throw new IOException("getFile request ran into status code error: " + resp.statusCode() + "with message: " + resp.getClass()); - } - return resp.body(); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/RequestLoggerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/RequestLoggerTest.java deleted file mode 100644 index 409af39ac60ad..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/RequestLoggerTest.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server; - -import io.airbyte.commons.io.IOs; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.helpers.LogClientSingleton; -import io.airbyte.config.helpers.LogConfigs; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import java.util.UUID; -import java.util.stream.Stream; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerResponseContext; -import lombok.RequiredArgsConstructor; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import org.slf4j.MDC; - -@SuppressWarnings({"PMD.AvoidPrintStackTrace", "PMD.JUnitTestsShouldIncludeAssert"}) -@ExtendWith(MockitoExtension.class) -class RequestLoggerTest { - - private static final String VALID_JSON_OBJECT = "{\"valid\":1}"; - private static final String INVALID_JSON_OBJECT = "invalid"; - private static final String ACCEPTED_CONTENT_TYPE = "application/json"; - private static final String NON_ACCEPTED_CONTENT_TYPE = "application/gzip"; - private static final String METHOD = "POST"; - private static final String REMOTE_ADDR = "123.456.789.101"; - private static final String URL = "/api/v1/test"; - private static final String REQUEST_BODY_PROPERTY = "requestBodyProperty"; - - private static final Random RANDOM = new Random(); - - @Mock - private HttpServletRequest mServletRequest; - - private Path logPath; - - @BeforeEach - void init() throws IOException { - Mockito.when(mServletRequest.getMethod()) - .thenReturn(METHOD); - Mockito.when(mServletRequest.getRemoteAddr()) - .thenReturn(REMOTE_ADDR); - Mockito.when(mServletRequest.getRequestURI()) - .thenReturn(URL); - - // set up the mdc so that actually log to a file, so that we can verify that file logging captures - // threads. - final Path jobRoot = Files.createTempDirectory(Path.of("/tmp"), "mdc_test"); - LogClientSingleton.getInstance().setJobMdc(WorkerEnvironment.DOCKER, - LogConfigs.EMPTY, - jobRoot); - logPath = jobRoot.resolve(LogClientSingleton.LOG_FILENAME); - } - - @Nested - @DisplayName("Formats logs correctly") - class RequestLoggerFormatsLogsCorrectly { - - private static final int ERROR_CODE = 401; - private static final int SUCCESS_CODE = 200; - private static final String errorPrefix = RequestLogger - .createLogPrefix(REMOTE_ADDR, METHOD, ERROR_CODE, URL) - .toString(); - private static final String successPrefix = RequestLogger - .createLogPrefix(REMOTE_ADDR, METHOD, SUCCESS_CODE, URL) - .toString(); - - static Stream logScenarios() { - return Stream.of( - Arguments.of(INVALID_JSON_OBJECT, NON_ACCEPTED_CONTENT_TYPE, ERROR_CODE, errorPrefix), - Arguments.of(INVALID_JSON_OBJECT, ACCEPTED_CONTENT_TYPE, ERROR_CODE, errorPrefix), - Arguments.of(VALID_JSON_OBJECT, NON_ACCEPTED_CONTENT_TYPE, ERROR_CODE, errorPrefix), - Arguments.of(VALID_JSON_OBJECT, ACCEPTED_CONTENT_TYPE, ERROR_CODE, errorPrefix + " - " + VALID_JSON_OBJECT), - Arguments.of(INVALID_JSON_OBJECT, NON_ACCEPTED_CONTENT_TYPE, SUCCESS_CODE, successPrefix), - Arguments.of(INVALID_JSON_OBJECT, ACCEPTED_CONTENT_TYPE, SUCCESS_CODE, successPrefix), - Arguments.of(VALID_JSON_OBJECT, NON_ACCEPTED_CONTENT_TYPE, SUCCESS_CODE, successPrefix), - Arguments.of(VALID_JSON_OBJECT, ACCEPTED_CONTENT_TYPE, SUCCESS_CODE, successPrefix + " - " + VALID_JSON_OBJECT)); - } - - @Mock - private ContainerRequestContext mRequestContext; - @Mock - private ContainerResponseContext mResponseContext; - - private RequestLogger requestLogger; - - @ParameterizedTest - @MethodSource("logScenarios") - @DisplayName("Check that the proper log is produced based on the scenario") - void test(final String requestBody, final String contentType, final int status, final String expectedLog) throws IOException { - // We have to instanciate the logger here, because the MDC config has been changed to log in a - // temporary file. - requestLogger = new RequestLogger(MDC.getCopyOfContextMap(), mServletRequest); - - stubRequestContext(mRequestContext, requestBody); - - Mockito.when(mResponseContext.getStatus()) - .thenReturn(status); - - Mockito.when(mServletRequest.getHeader("Content-Type")) - .thenReturn(contentType); - - // This is call to set the requestBody variable in the RequestLogger - requestLogger.filter(mRequestContext); - requestLogger.filter(mRequestContext, mResponseContext); - - final String expectedLogLevel = status == SUCCESS_CODE ? "INFO" : "ERROR"; - - final String logs = IOs.readFile(logPath); - final Stream matchingLines = logs.lines() - .filter(line -> line.endsWith(expectedLog)) - .filter(line -> line.contains(expectedLogLevel)); - - Assertions.assertThat(matchingLines).hasSize(1); - } - - } - - @Nested - @DisplayName("Logs correct requestBody") - class RequestLoggerCorrectRequestBody { - - /** - * This is a complex test that was written to prove that our requestLogger had a concurrency bug - * that caused incorrect request bodies to be logged. The RequestLogger originally used an instance - * variable that held the requestBody, which was written to by the request filter, and read by the - * response filter to generate a response log line that contained the original request body. If - * multiple requests were being processed at the same time, it was possible for the request filter - * of one request to overwrite the requestBody instance variable before the response log line was - * generated. The fixed implementation sets the requestBody as a custom property on the - * ContainerRequestFilter in the first filter method, and reads the custom requestBody property from - * the ContainerRequestFilter in the second filter method. - *

- * To cover this race condition, this test creates a single RequestLogger instance that is - * referenced from 100 threads. Each thread logs a unique request body. The main thread waits for - * all threads to finish, and then assures that every unique request body is included in the logs. - *

- * This test fails when using the instance variable approach for recording request bodies, because - * some request bodies are overwritten before they can be logged. - */ - @Test - void testRequestBodyConsistency() { - Mockito.when(mServletRequest.getHeader("Content-Type")) - .thenReturn(ACCEPTED_CONTENT_TYPE); - - final RequestLogger requestLogger = new RequestLogger(MDC.getCopyOfContextMap(), mServletRequest); - - final List testCases = new ArrayList<>(); - final List threads = new ArrayList<>(); - - for (int i = 1; i < 100; i++) { - testCases.add(createRunnableTestCase(requestLogger, UUID.randomUUID())); - } - - testCases.forEach(testCase -> { - final Thread thread = new Thread(testCase); - threads.add(thread); - thread.start(); - }); - - threads.forEach(thread -> { - try { - thread.join(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - }); - - testCases.forEach(testCase -> Assertions.assertThat(testCase.requestBodyWasLogged()).isTrue()); - } - - private RequestResponseRunnable createRunnableTestCase(final RequestLogger requestLogger, final UUID threadIdentifier) { - - // create thread-specific context mocks - final ContainerRequestContext mRequestContext = Mockito.mock(ContainerRequestContext.class); - final ContainerResponseContext mResponseContext = Mockito.mock(ContainerResponseContext.class); - - final String expectedRequestBody = String.format("{\"threadIdentifier\":\"%s\"}", threadIdentifier); - - stubRequestContext(mRequestContext, expectedRequestBody); - - return new RequestResponseRunnable(requestLogger, expectedRequestBody, mRequestContext, mResponseContext); - } - - @RequiredArgsConstructor - class RequestResponseRunnable implements Runnable { - - private final RequestLogger requestLogger; - private final String expectedRequestBody; - private final ContainerRequestContext mRequestContext; - private final ContainerResponseContext mResponseContext; - - @Override - public void run() { - try { - requestLogger.filter(mRequestContext); - Thread.sleep(RANDOM.nextInt(1000)); // random sleep to make race more likely - requestLogger.filter(mRequestContext, mResponseContext); - } catch (final IOException | InterruptedException e) { - e.printStackTrace(); - } - } - - // search all log lines to see if this thread's request body was logged - Boolean requestBodyWasLogged() { - return IOs.readFile(logPath).lines().anyMatch(line -> line.contains(expectedRequestBody)); - } - - } - - } - - private void stubRequestContext(final ContainerRequestContext mockContainerRequestContext, final String requestBody) { - Mockito.when(mockContainerRequestContext.getMethod()) - .thenReturn(METHOD); - - Mockito.when(mockContainerRequestContext.getEntityStream()) - .thenReturn(new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8))); - - Mockito.when(mockContainerRequestContext.getProperty(REQUEST_BODY_PROPERTY)).thenReturn(requestBody); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogConverterTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogConverterTest.java deleted file mode 100644 index 32eec2e432649..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogConverterTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import static io.airbyte.commons.server.helpers.ConnectionHelpers.FIELD_NAME; -import static io.airbyte.commons.server.helpers.ConnectionHelpers.SECOND_FIELD_NAME; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.airbyte.api.model.generated.DestinationSyncMode; -import io.airbyte.api.model.generated.SelectedFieldInfo; -import io.airbyte.api.model.generated.SyncMode; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.helpers.ConnectionHelpers; -import io.airbyte.config.DataType; -import io.airbyte.config.FieldSelectionData; -import io.airbyte.validation.json.JsonValidationException; -import java.util.List; -import org.junit.jupiter.api.Test; - -class CatalogConverterTest { - - @Test - void testConvertToProtocol() throws JsonValidationException { - assertEquals(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog(), - CatalogConverter.toConfiguredProtocol(ConnectionHelpers.generateBasicApiCatalog())); - } - - @Test - void testConvertToAPI() { - assertEquals(ConnectionHelpers.generateBasicApiCatalog(), CatalogConverter.toApi(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog(), - new FieldSelectionData())); - } - - @Test - void testEnumConversion() { - assertTrue(Enums.isCompatible(io.airbyte.api.model.generated.DataType.class, DataType.class)); - assertTrue(Enums.isCompatible(io.airbyte.config.SyncMode.class, io.airbyte.api.model.generated.SyncMode.class)); - } - - @Test - void testConvertToProtocolColumnSelectionValidation() { - assertThrows(JsonValidationException.class, () -> { - // fieldSelectionEnabled=true but selectedFields=null. - final var catalog = ConnectionHelpers.generateBasicApiCatalog(); - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).selectedFields(null); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertThrows(JsonValidationException.class, () -> { - // JSON schema has no `properties` node. - final var catalog = ConnectionHelpers.generateBasicApiCatalog(); - ((ObjectNode) catalog.getStreams().get(0).getStream().getJsonSchema()).remove("properties"); - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem("foo")); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertThrows(JsonValidationException.class, () -> { - // SelectedFieldInfo with empty path. - final var catalog = ConnectionHelpers.generateBasicApiCatalog(); - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo()); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertThrows(UnsupportedOperationException.class, () -> { - // SelectedFieldInfo with nested field path. - final var catalog = ConnectionHelpers.generateBasicApiCatalog(); - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true) - .addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem("foo").addFieldPathItem("bar")); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertThrows(JsonValidationException.class, () -> { - // SelectedFieldInfo with empty path. - final var catalog = ConnectionHelpers.generateBasicApiCatalog(); - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem("foo")); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertThrows(JsonValidationException.class, () -> { - final var catalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - // Only FIELD_NAME is selected. - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME)); - // The sync mode is INCREMENTAL and SECOND_FIELD_NAME is a cursor field. - catalog.getStreams().get(0).getConfig().syncMode(SyncMode.INCREMENTAL).cursorField(List.of(SECOND_FIELD_NAME)); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertDoesNotThrow(() -> { - final var catalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - // Only FIELD_NAME is selected. - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME)); - // The cursor field is not selected, but it's okay because it's FULL_REFRESH so it doesn't throw. - catalog.getStreams().get(0).getConfig().syncMode(SyncMode.FULL_REFRESH).cursorField(List.of(SECOND_FIELD_NAME)); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertThrows(JsonValidationException.class, () -> { - final var catalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - // Only FIELD_NAME is selected. - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME)); - // The destination sync mode is DEDUP and SECOND_FIELD_NAME is a primary key. - catalog.getStreams().get(0).getConfig().destinationSyncMode(DestinationSyncMode.APPEND_DEDUP).primaryKey(List.of(List.of(SECOND_FIELD_NAME))); - CatalogConverter.toConfiguredProtocol(catalog); - }); - - assertDoesNotThrow(() -> { - final var catalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - // Only FIELD_NAME is selected. - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME)); - // The primary key is not selected but that's okay because the destination sync mode is OVERWRITE. - catalog.getStreams().get(0).getConfig().destinationSyncMode(DestinationSyncMode.OVERWRITE).primaryKey(List.of(List.of(SECOND_FIELD_NAME))); - CatalogConverter.toConfiguredProtocol(catalog); - }); - } - - @Test - void testConvertToProtocolFieldSelection() throws JsonValidationException { - final var catalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME)); - assertEquals(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog(), CatalogConverter.toConfiguredProtocol(catalog)); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogDiffConvertersTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogDiffConvertersTest.java deleted file mode 100644 index f419597c00720..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/CatalogDiffConvertersTest.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.airbyte.api.model.generated.FieldTransform; -import io.airbyte.api.model.generated.StreamTransform; -import io.airbyte.commons.enums.Enums; -import io.airbyte.protocol.models.transform_models.FieldTransformType; -import io.airbyte.protocol.models.transform_models.StreamTransformType; -import org.junit.jupiter.api.Test; - -class CatalogDiffConvertersTest { - - @Test - void testEnumConversion() { - assertTrue(Enums.isCompatible(StreamTransform.TransformTypeEnum.class, StreamTransformType.class)); - assertTrue(Enums.isCompatible(FieldTransform.TransformTypeEnum.class, FieldTransformType.class)); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/ConfigurationUpdateTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/ConfigurationUpdateTest.java deleted file mode 100644 index eb565179128c5..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/ConfigurationUpdateTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.ImmutableMap; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.db.jdbc.JdbcUtils; -import io.airbyte.protocol.models.CatalogHelpers; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.protocol.models.Field; -import io.airbyte.protocol.models.JsonSchemaType; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class ConfigurationUpdateTest { - - private static final String IMAGE_REPOSITORY = "foo"; - private static final String IMAGE_TAG = "bar"; - private static final UUID UUID1 = UUID.randomUUID(); - private static final UUID UUID2 = UUID.randomUUID(); - private static final JsonNode SPEC = CatalogHelpers.fieldsToJsonSchema( - Field.of(JdbcUtils.USERNAME_KEY, JsonSchemaType.STRING), - Field.of(JdbcUtils.PASSWORD_KEY, JsonSchemaType.STRING)); - private static final ConnectorSpecification CONNECTOR_SPECIFICATION = new ConnectorSpecification().withConnectionSpecification(SPEC); - private static final JsonNode ORIGINAL_CONFIGURATION = Jsons.jsonNode(ImmutableMap.builder() - .put(JdbcUtils.USERNAME_KEY, "airbyte") - .put(JdbcUtils.PASSWORD_KEY, "abc") - .build()); - private static final JsonNode NEW_CONFIGURATION = Jsons.jsonNode(ImmutableMap.builder() - .put(JdbcUtils.USERNAME_KEY, "airbyte") - .put(JdbcUtils.PASSWORD_KEY, "xyz") - .build()); - private static final StandardSourceDefinition SOURCE_DEFINITION = new StandardSourceDefinition() - .withDockerRepository(IMAGE_REPOSITORY) - .withDockerImageTag(IMAGE_TAG) - .withSpec(CONNECTOR_SPECIFICATION); - private static final SourceConnection ORIGINAL_SOURCE_CONNECTION = new SourceConnection() - .withSourceId(UUID1) - .withSourceDefinitionId(UUID2) - .withConfiguration(ORIGINAL_CONFIGURATION); - private static final SourceConnection NEW_SOURCE_CONNECTION = new SourceConnection() - .withSourceId(UUID1) - .withSourceDefinitionId(UUID2) - .withConfiguration(NEW_CONFIGURATION); - private static final StandardDestinationDefinition DESTINATION_DEFINITION = new StandardDestinationDefinition() - .withDockerRepository(IMAGE_REPOSITORY) - .withDockerImageTag(IMAGE_TAG) - .withSpec(CONNECTOR_SPECIFICATION); - private static final DestinationConnection ORIGINAL_DESTINATION_CONNECTION = new DestinationConnection() - .withDestinationId(UUID1) - .withDestinationDefinitionId(UUID2) - .withConfiguration(ORIGINAL_CONFIGURATION); - private static final DestinationConnection NEW_DESTINATION_CONNECTION = new DestinationConnection() - .withDestinationId(UUID1) - .withDestinationDefinitionId(UUID2) - .withConfiguration(NEW_CONFIGURATION); - - private ConfigRepository configRepository; - private SecretsRepositoryReader secretsRepositoryReader; - private JsonSecretsProcessor secretsProcessor; - private ConfigurationUpdate configurationUpdate; - - @BeforeEach - void setup() { - configRepository = mock(ConfigRepository.class); - secretsRepositoryReader = mock(SecretsRepositoryReader.class); - secretsProcessor = mock(JsonSecretsProcessor.class); - - configurationUpdate = new ConfigurationUpdate(configRepository, secretsRepositoryReader, secretsProcessor); - } - - @Test - void testSourceUpdate() throws JsonValidationException, IOException, ConfigNotFoundException { - when(secretsRepositoryReader.getSourceConnectionWithSecrets(UUID1)).thenReturn(ORIGINAL_SOURCE_CONNECTION); - when(configRepository.getStandardSourceDefinition(UUID2)).thenReturn(SOURCE_DEFINITION); - when(secretsProcessor.copySecrets(ORIGINAL_CONFIGURATION, NEW_CONFIGURATION, SPEC)).thenReturn(NEW_CONFIGURATION); - - final SourceConnection actual = configurationUpdate.source(UUID1, ORIGINAL_SOURCE_CONNECTION.getName(), NEW_CONFIGURATION); - - assertEquals(NEW_SOURCE_CONNECTION, actual); - } - - @Test - void testDestinationUpdate() throws JsonValidationException, IOException, ConfigNotFoundException { - when(secretsRepositoryReader.getDestinationConnectionWithSecrets(UUID1)).thenReturn(ORIGINAL_DESTINATION_CONNECTION); - when(configRepository.getStandardDestinationDefinition(UUID2)).thenReturn(DESTINATION_DEFINITION); - when(secretsProcessor.copySecrets(ORIGINAL_CONFIGURATION, NEW_CONFIGURATION, SPEC)).thenReturn(NEW_CONFIGURATION); - - final DestinationConnection actual = configurationUpdate.destination(UUID1, ORIGINAL_DESTINATION_CONNECTION.getName(), NEW_CONFIGURATION); - - assertEquals(NEW_DESTINATION_CONNECTION, actual); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/JobConverterTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/JobConverterTest.java deleted file mode 100644 index f6289e3758592..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/JobConverterTest.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.AttemptFailureOrigin; -import io.airbyte.api.model.generated.AttemptFailureReason; -import io.airbyte.api.model.generated.AttemptFailureSummary; -import io.airbyte.api.model.generated.AttemptFailureType; -import io.airbyte.api.model.generated.AttemptInfoRead; -import io.airbyte.api.model.generated.AttemptRead; -import io.airbyte.api.model.generated.AttemptStats; -import io.airbyte.api.model.generated.AttemptStreamStats; -import io.airbyte.api.model.generated.DestinationDefinitionRead; -import io.airbyte.api.model.generated.JobConfigType; -import io.airbyte.api.model.generated.JobDebugRead; -import io.airbyte.api.model.generated.JobInfoLightRead; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.JobRead; -import io.airbyte.api.model.generated.JobWithAttemptsRead; -import io.airbyte.api.model.generated.LogRead; -import io.airbyte.api.model.generated.ResetConfig; -import io.airbyte.api.model.generated.SourceDefinitionRead; -import io.airbyte.api.model.generated.StreamDescriptor; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.FailureReason; -import io.airbyte.config.FailureReason.FailureOrigin; -import io.airbyte.config.FailureReason.FailureType; -import io.airbyte.config.JobConfig; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.JobOutput; -import io.airbyte.config.JobOutput.OutputType; -import io.airbyte.config.JobResetConnectionConfig; -import io.airbyte.config.JobSyncConfig; -import io.airbyte.config.ResetSourceConfiguration; -import io.airbyte.config.StandardSyncOutput; -import io.airbyte.config.StandardSyncSummary; -import io.airbyte.config.StreamSyncStats; -import io.airbyte.config.SyncStats; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.persistence.job.models.Attempt; -import io.airbyte.persistence.job.models.AttemptStatus; -import io.airbyte.persistence.job.models.Job; -import io.airbyte.persistence.job.models.JobStatus; -import io.airbyte.protocol.models.AirbyteStream; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.protocol.models.ConfiguredAirbyteStream; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class JobConverterTest { - - private static final long JOB_ID = 100L; - private static final Integer ATTEMPT_NUMBER = 0; - private static final String JOB_CONFIG_ID = "123"; - private static final JobStatus JOB_STATUS = JobStatus.RUNNING; - private static final AttemptStatus ATTEMPT_STATUS = AttemptStatus.RUNNING; - private static final JobConfig.ConfigType CONFIG_TYPE = ConfigType.SYNC; - private static final Path LOG_PATH = Path.of("log_path"); - private static final long CREATED_AT = System.currentTimeMillis() / 1000; - private static final long RECORDS_EMITTED = 15L; - private static final long BYTES_EMITTED = 100L; - private static final long RECORDS_COMMITTED = 10L; - private static final long STATE_MESSAGES_EMITTED = 2L; - private static final String STREAM_NAME = "stream1"; - private static final String FAILURE_EXTERNAL_MESSAGE = "something went wrong"; - private static final long FAILURE_TIMESTAMP = System.currentTimeMillis(); - private static final String FAILURE_STACKTRACE = "stacktrace"; - private static final boolean PARTIAL_SUCCESS = false; - - private static final JobConfig JOB_CONFIG = new JobConfig() - .withConfigType(CONFIG_TYPE) - .withSync(new JobSyncConfig().withConfiguredAirbyteCatalog(new ConfiguredAirbyteCatalog().withStreams(List.of( - new ConfiguredAirbyteStream().withStream(new AirbyteStream().withName("users")), - new ConfiguredAirbyteStream().withStream(new AirbyteStream().withName("accounts")))))); - - private static final JobOutput JOB_OUTPUT = new JobOutput() - .withOutputType(OutputType.SYNC) - .withSync(new StandardSyncOutput() - .withStandardSyncSummary(new StandardSyncSummary() - .withRecordsSynced(RECORDS_EMITTED) - .withBytesSynced(BYTES_EMITTED) - .withTotalStats(new SyncStats() - .withRecordsEmitted(RECORDS_EMITTED) - .withBytesEmitted(BYTES_EMITTED) - .withSourceStateMessagesEmitted(STATE_MESSAGES_EMITTED) - .withRecordsCommitted(RECORDS_COMMITTED)) - .withStreamStats(Lists.newArrayList(new StreamSyncStats() - .withStreamName(STREAM_NAME) - .withStats(new SyncStats() - .withRecordsEmitted(RECORDS_EMITTED) - .withBytesEmitted(BYTES_EMITTED) - .withSourceStateMessagesEmitted(STATE_MESSAGES_EMITTED) - .withRecordsCommitted(RECORDS_COMMITTED)))))); - - private JobConverter jobConverter; - private Job job; - - private static final JobInfoRead JOB_INFO = - new JobInfoRead() - .job(new JobRead() - .id(JOB_ID) - .configId(JOB_CONFIG_ID) - .status(io.airbyte.api.model.generated.JobStatus.RUNNING) - .configType(JobConfigType.SYNC) - .createdAt(CREATED_AT) - .updatedAt(CREATED_AT)) - .attempts(Lists.newArrayList(new AttemptInfoRead() - .attempt(new AttemptRead() - .id((long) ATTEMPT_NUMBER) - .status(io.airbyte.api.model.generated.AttemptStatus.RUNNING) - .recordsSynced(RECORDS_EMITTED) - .bytesSynced(BYTES_EMITTED) - .totalStats(new AttemptStats() - .recordsEmitted(RECORDS_EMITTED) - .bytesEmitted(BYTES_EMITTED) - .stateMessagesEmitted(STATE_MESSAGES_EMITTED) - .recordsCommitted(RECORDS_COMMITTED)) - .streamStats(Lists.newArrayList(new AttemptStreamStats() - .streamName(STREAM_NAME) - .stats(new AttemptStats() - .recordsEmitted(RECORDS_EMITTED) - .bytesEmitted(BYTES_EMITTED) - .stateMessagesEmitted(STATE_MESSAGES_EMITTED) - .recordsCommitted(RECORDS_COMMITTED)))) - .updatedAt(CREATED_AT) - .createdAt(CREATED_AT) - .endedAt(CREATED_AT) - .failureSummary(new AttemptFailureSummary() - .failures(Lists.newArrayList(new AttemptFailureReason() - .failureOrigin(AttemptFailureOrigin.SOURCE) - .failureType(AttemptFailureType.SYSTEM_ERROR) - .externalMessage(FAILURE_EXTERNAL_MESSAGE) - .stacktrace(FAILURE_STACKTRACE) - .timestamp(FAILURE_TIMESTAMP))) - .partialSuccess(PARTIAL_SUCCESS))) - .logs(new LogRead().logLines(new ArrayList<>())))); - - private static final String version = "0.33.4"; - private static final AirbyteVersion airbyteVersion = new AirbyteVersion(version); - private static final SourceDefinitionRead sourceDefinitionRead = new SourceDefinitionRead().sourceDefinitionId(UUID.randomUUID()); - private static final DestinationDefinitionRead destinationDefinitionRead = - new DestinationDefinitionRead().destinationDefinitionId(UUID.randomUUID()); - - private static final JobDebugRead JOB_DEBUG_INFO = - new JobDebugRead() - .id(JOB_ID) - .configId(JOB_CONFIG_ID) - .status(io.airbyte.api.model.generated.JobStatus.RUNNING) - .configType(JobConfigType.SYNC) - .airbyteVersion(airbyteVersion.serialize()) - .sourceDefinition(sourceDefinitionRead) - .destinationDefinition(destinationDefinitionRead); - - private static final JobWithAttemptsRead JOB_WITH_ATTEMPTS_READ = new JobWithAttemptsRead() - .job(JOB_INFO.getJob()) - .attempts(JOB_INFO.getAttempts().stream().map(AttemptInfoRead::getAttempt).collect(Collectors.toList())); - - private static final io.airbyte.config.AttemptFailureSummary FAILURE_SUMMARY = new io.airbyte.config.AttemptFailureSummary() - .withFailures(Lists.newArrayList(new FailureReason() - .withFailureOrigin(FailureOrigin.SOURCE) - .withFailureType(FailureType.SYSTEM_ERROR) - .withExternalMessage(FAILURE_EXTERNAL_MESSAGE) - .withStacktrace(FAILURE_STACKTRACE) - .withTimestamp(FAILURE_TIMESTAMP))) - .withPartialSuccess(PARTIAL_SUCCESS); - - @BeforeEach - public void setUp() { - jobConverter = new JobConverter(WorkerEnvironment.DOCKER, LogConfigs.EMPTY); - job = mock(Job.class); - final Attempt attempt = mock(Attempt.class); - when(job.getId()).thenReturn(JOB_ID); - when(job.getConfigType()).thenReturn(JOB_CONFIG.getConfigType()); - when(job.getScope()).thenReturn(JOB_CONFIG_ID); - when(job.getConfig()).thenReturn(JOB_CONFIG); - when(job.getStatus()).thenReturn(JOB_STATUS); - when(job.getCreatedAtInSecond()).thenReturn(CREATED_AT); - when(job.getUpdatedAtInSecond()).thenReturn(CREATED_AT); - when(job.getAttempts()).thenReturn(Lists.newArrayList(attempt)); - when(attempt.getAttemptNumber()).thenReturn(ATTEMPT_NUMBER); - when(attempt.getStatus()).thenReturn(ATTEMPT_STATUS); - when(attempt.getOutput()).thenReturn(Optional.of(JOB_OUTPUT)); - when(attempt.getLogPath()).thenReturn(LOG_PATH); - when(attempt.getCreatedAtInSecond()).thenReturn(CREATED_AT); - when(attempt.getUpdatedAtInSecond()).thenReturn(CREATED_AT); - when(attempt.getEndedAtInSecond()).thenReturn(Optional.of(CREATED_AT)); - when(attempt.getFailureSummary()).thenReturn(Optional.of(FAILURE_SUMMARY)); - - } - - @Test - void testGetJobInfoRead() { - assertEquals(JOB_INFO, jobConverter.getJobInfoRead(job)); - } - - @Test - void testGetJobInfoLightRead() { - final JobInfoLightRead expected = new JobInfoLightRead().job(JOB_INFO.getJob()); - assertEquals(expected, jobConverter.getJobInfoLightRead(job)); - } - - @Test - void testGetDebugJobInfoRead() { - assertEquals(JOB_DEBUG_INFO, JobConverter.getDebugJobInfoRead(JOB_INFO, sourceDefinitionRead, destinationDefinitionRead, airbyteVersion)); - } - - @Test - void testGetJobWithAttemptsRead() { - assertEquals(JOB_WITH_ATTEMPTS_READ, JobConverter.getJobWithAttemptsRead(job)); - } - - @Test - void testGetJobRead() { - final JobWithAttemptsRead jobReadActual = JobConverter.getJobWithAttemptsRead(job); - assertEquals(JOB_WITH_ATTEMPTS_READ, jobReadActual); - } - - @Test - void testEnumConversion() { - assertTrue(Enums.isCompatible(JobConfig.ConfigType.class, JobConfigType.class)); - assertTrue(Enums.isCompatible(JobStatus.class, io.airbyte.api.model.generated.JobStatus.class)); - assertTrue(Enums.isCompatible(AttemptStatus.class, io.airbyte.api.model.generated.AttemptStatus.class)); - assertTrue(Enums.isCompatible(FailureReason.FailureOrigin.class, io.airbyte.api.model.generated.AttemptFailureOrigin.class)); - } - - // this test intentionally only looks at the reset config as the rest is the same here. - @Test - void testResetJobIncludesResetConfig() { - final JobConfig resetConfig = new JobConfig() - .withConfigType(ConfigType.RESET_CONNECTION) - .withResetConnection(new JobResetConnectionConfig().withResetSourceConfiguration(new ResetSourceConfiguration().withStreamsToReset(List.of( - new io.airbyte.protocol.models.StreamDescriptor().withName("users"), - new io.airbyte.protocol.models.StreamDescriptor().withName("accounts"))))); - final Job resetJob = new Job( - JOB_ID, - ConfigType.RESET_CONNECTION, - JOB_CONFIG_ID, - resetConfig, - Collections.emptyList(), - JobStatus.SUCCEEDED, - CREATED_AT, - CREATED_AT, - CREATED_AT); - - final ResetConfig expectedResetConfig = new ResetConfig().streamsToReset(List.of( - new StreamDescriptor().name("users"), - new StreamDescriptor().name("accounts"))); - assertEquals(expectedResetConfig, jobConverter.getJobInfoRead(resetJob).getJob().getResetConfig()); - } - - @Test - void testResetJobExcludesConfigIfNull() { - final JobConfig resetConfig = new JobConfig() - .withConfigType(ConfigType.RESET_CONNECTION) - .withResetConnection(new JobResetConnectionConfig().withResetSourceConfiguration(null)); - final Job resetJob = new Job( - JOB_ID, - ConfigType.RESET_CONNECTION, - JOB_CONFIG_ID, - resetConfig, - Collections.emptyList(), - JobStatus.SUCCEEDED, - CREATED_AT, - CREATED_AT, - CREATED_AT); - - assertNull(jobConverter.getJobInfoRead(resetJob).getJob().getResetConfig()); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/OauthModelConverterTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/OauthModelConverterTest.java deleted file mode 100644 index 40f484c329980..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/converters/OauthModelConverterTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.converters; - -import static org.junit.jupiter.api.Assertions.*; - -import io.airbyte.protocol.models.AuthSpecification; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.protocol.models.OAuth2Specification; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class OauthModelConverterTest { - - private static Stream testProvider() { - return Stream.of( - // all fields filled out with nesting - Arguments.of( - List.of(List.of("init1"), List.of("init2-1", "init2-2")), - List.of(List.of("output1"), List.of("output2-1", "output2-2")), - List.of("path", "nestedPath", 1)), - // init params only - Arguments.of( - List.of(List.of("init1"), List.of("init2-1", "init2-2")), - List.of(List.of()), - List.of()), - // output params only - Arguments.of( - List.of(List.of()), - List.of(List.of("output1"), List.of("output2-1", "output2-2")), - List.of()), - // rootObject only - Arguments.of( - List.of(List.of()), - List.of(List.of()), - List.of("path", "nestedPath", 1))); - } - - @ParameterizedTest - @MethodSource("testProvider") - void testIt(final List> initParams, final List> outputParams, final List rootObject) { - final ConnectorSpecification input = new ConnectorSpecification().withAuthSpecification( - new AuthSpecification() - .withAuthType(AuthSpecification.AuthType.OAUTH_2_0) - .withOauth2Specification(new OAuth2Specification() - .withOauthFlowInitParameters(initParams) - .withOauthFlowOutputParameters(outputParams) - .withRootObject(rootObject))); - - final io.airbyte.api.model.generated.AuthSpecification expected = new io.airbyte.api.model.generated.AuthSpecification() - .authType(io.airbyte.api.model.generated.AuthSpecification.AuthTypeEnum.OAUTH2_0) - .oauth2Specification( - new io.airbyte.api.model.generated.OAuth2Specification() - .oauthFlowInitParameters(initParams) - .oauthFlowOutputParameters(outputParams) - .rootObject(rootObject)); - - final Optional authSpec = OauthModelConverter.getAuthSpec(input); - assertTrue(authSpec.isPresent()); - assertEquals(expected, authSpec.get()); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/AttemptHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/AttemptHandlerTest.java deleted file mode 100644 index 9f6e5f7846324..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/AttemptHandlerTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doThrow; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.api.model.generated.AttemptSyncConfig; -import io.airbyte.api.model.generated.ConnectionState; -import io.airbyte.api.model.generated.ConnectionStateType; -import io.airbyte.api.model.generated.GlobalState; -import io.airbyte.api.model.generated.SaveAttemptSyncConfigRequestBody; -import io.airbyte.api.model.generated.SetWorkflowInAttemptRequestBody; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.persistence.job.JobPersistence; -import java.io.IOException; -import java.util.Map; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -class AttemptHandlerTest { - - JobPersistence jobPersistence; - AttemptHandler handler; - - private static final UUID CONNECTION_ID = UUID.randomUUID(); - private static final long JOB_ID = 10002L; - private static final int ATTEMPT_NUMBER = 1; - - private static final String PROCESSING_TASK_QUEUE = "SYNC"; - - @BeforeEach - public void init() { - jobPersistence = Mockito.mock(JobPersistence.class); - handler = new AttemptHandler(jobPersistence); - } - - @Test - void testInternalWorkerHandlerSetsTemporalWorkflowId() throws Exception { - final String workflowId = UUID.randomUUID().toString(); - - final ArgumentCaptor attemptNumberCapture = ArgumentCaptor.forClass(Integer.class); - final ArgumentCaptor jobIdCapture = ArgumentCaptor.forClass(Long.class); - final ArgumentCaptor workflowIdCapture = ArgumentCaptor.forClass(String.class); - final ArgumentCaptor queueCapture = ArgumentCaptor.forClass(String.class); - - final SetWorkflowInAttemptRequestBody requestBody = - new SetWorkflowInAttemptRequestBody().attemptNumber(ATTEMPT_NUMBER).jobId(JOB_ID).workflowId(workflowId) - .processingTaskQueue(PROCESSING_TASK_QUEUE); - - assertTrue(handler.setWorkflowInAttempt(requestBody).getSucceeded()); - - Mockito.verify(jobPersistence).setAttemptTemporalWorkflowInfo(jobIdCapture.capture(), attemptNumberCapture.capture(), workflowIdCapture.capture(), - queueCapture.capture()); - - assertEquals(ATTEMPT_NUMBER, attemptNumberCapture.getValue()); - assertEquals(JOB_ID, jobIdCapture.getValue()); - assertEquals(workflowId, workflowIdCapture.getValue()); - assertEquals(PROCESSING_TASK_QUEUE, queueCapture.getValue()); - } - - @Test - void testInternalWorkerHandlerSetsTemporalWorkflowIdThrows() throws Exception { - final String workflowId = UUID.randomUUID().toString(); - - doThrow(IOException.class).when(jobPersistence).setAttemptTemporalWorkflowInfo(anyLong(), anyInt(), - any(), any()); - - final ArgumentCaptor attemptNumberCapture = ArgumentCaptor.forClass(Integer.class); - final ArgumentCaptor jobIdCapture = ArgumentCaptor.forClass(Long.class); - final ArgumentCaptor workflowIdCapture = ArgumentCaptor.forClass(String.class); - final ArgumentCaptor queueCapture = ArgumentCaptor.forClass(String.class); - - final SetWorkflowInAttemptRequestBody requestBody = - new SetWorkflowInAttemptRequestBody().attemptNumber(ATTEMPT_NUMBER).jobId(JOB_ID).workflowId(workflowId) - .processingTaskQueue(PROCESSING_TASK_QUEUE); - - assertFalse(handler.setWorkflowInAttempt(requestBody).getSucceeded()); - - Mockito.verify(jobPersistence).setAttemptTemporalWorkflowInfo(jobIdCapture.capture(), attemptNumberCapture.capture(), workflowIdCapture.capture(), - queueCapture.capture()); - - assertEquals(ATTEMPT_NUMBER, attemptNumberCapture.getValue()); - assertEquals(JOB_ID, jobIdCapture.getValue()); - assertEquals(workflowId, workflowIdCapture.getValue()); - assertEquals(PROCESSING_TASK_QUEUE, queueCapture.getValue()); - } - - @Test - void testInternalHandlerSetsAttemptSyncConfig() throws Exception { - final ArgumentCaptor attemptNumberCapture = ArgumentCaptor.forClass(Integer.class); - final ArgumentCaptor jobIdCapture = ArgumentCaptor.forClass(Long.class); - final ArgumentCaptor attemptSyncConfigCapture = - ArgumentCaptor.forClass(io.airbyte.config.AttemptSyncConfig.class); - - final JsonNode sourceConfig = Jsons.jsonNode(Map.of("source_key", "source_val")); - final JsonNode destinationConfig = Jsons.jsonNode(Map.of("destination_key", "destination_val")); - final ConnectionState state = new ConnectionState() - .connectionId(CONNECTION_ID) - .stateType(ConnectionStateType.GLOBAL) - .streamState(null) - .globalState(new GlobalState().sharedState(Jsons.jsonNode(Map.of("state_key", "state_val")))); - - final AttemptSyncConfig attemptSyncConfig = new AttemptSyncConfig() - .destinationConfiguration(destinationConfig) - .sourceConfiguration(sourceConfig) - .state(state); - - final SaveAttemptSyncConfigRequestBody requestBody = - new SaveAttemptSyncConfigRequestBody().attemptNumber(ATTEMPT_NUMBER).jobId(JOB_ID).syncConfig(attemptSyncConfig); - - assertTrue(handler.saveSyncConfig(requestBody).getSucceeded()); - - Mockito.verify(jobPersistence).writeAttemptSyncConfig(jobIdCapture.capture(), attemptNumberCapture.capture(), attemptSyncConfigCapture.capture()); - - final io.airbyte.config.AttemptSyncConfig expectedAttemptSyncConfig = ApiPojoConverters.attemptSyncConfigToInternal(attemptSyncConfig); - - assertEquals(ATTEMPT_NUMBER, attemptNumberCapture.getValue()); - assertEquals(JOB_ID, jobIdCapture.getValue()); - assertEquals(expectedAttemptSyncConfig, attemptSyncConfigCapture.getValue()); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionSchedulerHelperTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionSchedulerHelperTest.java deleted file mode 100644 index 238b2f95427b0..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionSchedulerHelperTest.java +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.airbyte.api.model.generated.ConnectionScheduleData; -import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; -import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule.TimeUnitEnum; -import io.airbyte.api.model.generated.ConnectionScheduleDataCron; -import io.airbyte.api.model.generated.ConnectionScheduleType; -import io.airbyte.commons.server.handlers.helpers.ConnectionScheduleHelper; -import io.airbyte.config.BasicSchedule.TimeUnit; -import io.airbyte.config.Schedule; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.ScheduleType; -import io.airbyte.validation.json.JsonValidationException; -import org.junit.jupiter.api.Test; - -class ConnectionSchedulerHelperTest { - - private final static String EXPECTED_CRON_TIMEZONE = "UTC"; - private final static String EXPECTED_CRON_EXPRESSION = "* */2 * * * ?"; - - @Test - void testPopulateSyncScheduleFromManualType() throws JsonValidationException { - final StandardSync actual = new StandardSync(); - ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, - ConnectionScheduleType.MANUAL, null); - assertTrue(actual.getManual()); - assertEquals(ScheduleType.MANUAL, actual.getScheduleType()); - assertNull(actual.getSchedule()); - assertNull(actual.getScheduleData()); - } - - @Test - void testPopulateSyncScheduleFromBasicType() throws JsonValidationException { - final StandardSync actual = new StandardSync(); - ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, - ConnectionScheduleType.BASIC, new ConnectionScheduleData() - .basicSchedule(new ConnectionScheduleDataBasicSchedule() - .timeUnit(TimeUnitEnum.HOURS) - .units(1L))); - assertFalse(actual.getManual()); - assertEquals(ScheduleType.BASIC_SCHEDULE, actual.getScheduleType()); - assertEquals(TimeUnit.HOURS, actual.getScheduleData().getBasicSchedule().getTimeUnit()); - assertEquals(1L, actual.getScheduleData().getBasicSchedule().getUnits()); - // We expect the old format to be dual-written. - assertEquals(Schedule.TimeUnit.HOURS, actual.getSchedule().getTimeUnit()); - assertEquals(1L, actual.getSchedule().getUnits()); - } - - @Test - void testPopulateSyncScheduleFromCron() throws JsonValidationException { - final StandardSync actual = new StandardSync(); - ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, - ConnectionScheduleType.CRON, new ConnectionScheduleData() - .cron(new ConnectionScheduleDataCron() - .cronTimeZone(EXPECTED_CRON_TIMEZONE) - .cronExpression(EXPECTED_CRON_EXPRESSION))); - assertEquals(ScheduleType.CRON, actual.getScheduleType()); - assertEquals(EXPECTED_CRON_TIMEZONE, actual.getScheduleData().getCron().getCronTimeZone()); - assertEquals(EXPECTED_CRON_EXPRESSION, actual.getScheduleData().getCron().getCronExpression()); - assertNull(actual.getSchedule()); - } - - @Test - void testScheduleValidation() { - final StandardSync actual = new StandardSync(); - assertThrows(JsonValidationException.class, () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, - ConnectionScheduleType.CRON, null)); - assertThrows(JsonValidationException.class, - () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.BASIC, new ConnectionScheduleData())); - assertThrows(JsonValidationException.class, - () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData())); - assertThrows(JsonValidationException.class, - () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData() - .cron(new ConnectionScheduleDataCron()))); - assertThrows(JsonValidationException.class, - () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData() - .cron(new ConnectionScheduleDataCron().cronExpression(EXPECTED_CRON_EXPRESSION).cronTimeZone("Etc/foo")))); - assertThrows(JsonValidationException.class, - () -> ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, ConnectionScheduleType.CRON, new ConnectionScheduleData() - .cron(new ConnectionScheduleDataCron().cronExpression("bad cron").cronTimeZone(EXPECTED_CRON_TIMEZONE)))); - } - - @Test - void testAvailableCronTimeZonesStayTheSame() { - /** - * NOTE: this test exists to make sure that the server stays in sync with the frontend. The list of - * supported timezones is copied from airbyte-webapp/src/config/availableCronTimeZones.json. If this - * test fails, then THAT file must be updated with the new timezones. - */ - String[] timezoneStrings = { - "Africa/Abidjan", - "Africa/Accra", - "Africa/Addis_Ababa", - "Africa/Algiers", - "Africa/Asmara", - "Africa/Asmera", - "Africa/Bamako", - "Africa/Bangui", - "Africa/Banjul", - "Africa/Bissau", - "Africa/Blantyre", - "Africa/Brazzaville", - "Africa/Bujumbura", - "Africa/Cairo", - "Africa/Casablanca", - "Africa/Ceuta", - "Africa/Conakry", - "Africa/Dakar", - "Africa/Dar_es_Salaam", - "Africa/Djibouti", - "Africa/Douala", - "Africa/El_Aaiun", - "Africa/Freetown", - "Africa/Gaborone", - "Africa/Harare", - "Africa/Johannesburg", - "Africa/Juba", - "Africa/Kampala", - "Africa/Khartoum", - "Africa/Kigali", - "Africa/Kinshasa", - "Africa/Lagos", - "Africa/Libreville", - "Africa/Lome", - "Africa/Luanda", - "Africa/Lubumbashi", - "Africa/Lusaka", - "Africa/Malabo", - "Africa/Maputo", - "Africa/Maseru", - "Africa/Mbabane", - "Africa/Mogadishu", - "Africa/Monrovia", - "Africa/Nairobi", - "Africa/Ndjamena", - "Africa/Niamey", - "Africa/Nouakchott", - "Africa/Ouagadougou", - "Africa/Porto-Novo", - "Africa/Sao_Tome", - "Africa/Timbuktu", - "Africa/Tripoli", - "Africa/Tunis", - "Africa/Windhoek", - "America/Adak", - "America/Anchorage", - "America/Anguilla", - "America/Antigua", - "America/Araguaina", - "America/Argentina/Buenos_Aires", - "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", - "America/Argentina/Cordoba", - "America/Argentina/Jujuy", - "America/Argentina/La_Rioja", - "America/Argentina/Mendoza", - "America/Argentina/Rio_Gallegos", - "America/Argentina/Salta", - "America/Argentina/San_Juan", - "America/Argentina/San_Luis", - "America/Argentina/Tucuman", - "America/Argentina/Ushuaia", - "America/Aruba", - "America/Asuncion", - "America/Atikokan", - "America/Atka", - "America/Bahia", - "America/Bahia_Banderas", - "America/Barbados", - "America/Belem", - "America/Belize", - "America/Blanc-Sablon", - "America/Boa_Vista", - "America/Bogota", - "America/Boise", - "America/Buenos_Aires", - "America/Cambridge_Bay", - "America/Campo_Grande", - "America/Cancun", - "America/Caracas", - "America/Catamarca", - "America/Cayenne", - "America/Cayman", - "America/Chicago", - "America/Chihuahua", - "America/Coral_Harbour", - "America/Cordoba", - "America/Costa_Rica", - "America/Creston", - "America/Cuiaba", - "America/Curacao", - "America/Danmarkshavn", - "America/Dawson", - "America/Dawson_Creek", - "America/Denver", - "America/Detroit", - "America/Dominica", - "America/Edmonton", - "America/Eirunepe", - "America/El_Salvador", - "America/Ensenada", - "America/Fort_Nelson", - "America/Fort_Wayne", - "America/Fortaleza", - "America/Glace_Bay", - "America/Godthab", - "America/Goose_Bay", - "America/Grand_Turk", - "America/Grenada", - "America/Guadeloupe", - "America/Guatemala", - "America/Guayaquil", - "America/Guyana", - "America/Halifax", - "America/Havana", - "America/Hermosillo", - "America/Indiana/Indianapolis", - "America/Indiana/Knox", - "America/Indiana/Marengo", - "America/Indiana/Petersburg", - "America/Indiana/Tell_City", - "America/Indiana/Vevay", - "America/Indiana/Vincennes", - "America/Indiana/Winamac", - "America/Indianapolis", - "America/Inuvik", - "America/Iqaluit", - "America/Jamaica", - "America/Jujuy", - "America/Juneau", - "America/Kentucky/Louisville", - "America/Kentucky/Monticello", - "America/Knox_IN", - "America/Kralendijk", - "America/La_Paz", - "America/Lima", - "America/Los_Angeles", - "America/Louisville", - "America/Lower_Princes", - "America/Maceio", - "America/Managua", - "America/Manaus", - "America/Marigot", - "America/Martinique", - "America/Matamoros", - "America/Mazatlan", - "America/Mendoza", - "America/Menominee", - "America/Merida", - "America/Metlakatla", - "America/Mexico_City", - "America/Miquelon", - "America/Moncton", - "America/Monterrey", - "America/Montevideo", - "America/Montreal", - "America/Montserrat", - "America/Nassau", - "America/New_York", - "America/Nipigon", - "America/Nome", - "America/Noronha", - "America/North_Dakota/Beulah", - "America/North_Dakota/Center", - "America/North_Dakota/New_Salem", - "America/Ojinaga", - "America/Panama", - "America/Pangnirtung", - "America/Paramaribo", - "America/Phoenix", - "America/Port-au-Prince", - "America/Port_of_Spain", - "America/Porto_Acre", - "America/Porto_Velho", - "America/Puerto_Rico", - "America/Punta_Arenas", - "America/Rainy_River", - "America/Rankin_Inlet", - "America/Recife", - "America/Regina", - "America/Resolute", - "America/Rio_Branco", - "America/Rosario", - "America/Santa_Isabel", - "America/Santarem", - "America/Santiago", - "America/Santo_Domingo", - "America/Sao_Paulo", - "America/Scoresbysund", - "America/Shiprock", - "America/Sitka", - "America/St_Barthelemy", - "America/St_Johns", - "America/St_Kitts", - "America/St_Lucia", - "America/St_Thomas", - "America/St_Vincent", - "America/Swift_Current", - "America/Tegucigalpa", - "America/Thule", - "America/Thunder_Bay", - "America/Tijuana", - "America/Toronto", - "America/Tortola", - "America/Vancouver", - "America/Virgin", - "America/Whitehorse", - "America/Winnipeg", - "America/Yakutat", - "America/Yellowknife", - "Antarctica/Casey", - "Antarctica/Davis", - "Antarctica/DumontDUrville", - "Antarctica/Macquarie", - "Antarctica/Mawson", - "Antarctica/McMurdo", - "Antarctica/Palmer", - "Antarctica/Rothera", - "Antarctica/South_Pole", - "Antarctica/Syowa", - "Antarctica/Troll", - "Antarctica/Vostok", - "Arctic/Longyearbyen", - "Asia/Aden", - "Asia/Almaty", - "Asia/Amman", - "Asia/Anadyr", - "Asia/Aqtau", - "Asia/Aqtobe", - "Asia/Ashgabat", - "Asia/Ashkhabad", - "Asia/Atyrau", - "Asia/Baghdad", - "Asia/Bahrain", - "Asia/Baku", - "Asia/Bangkok", - "Asia/Barnaul", - "Asia/Beirut", - "Asia/Bishkek", - "Asia/Brunei", - "Asia/Calcutta", - "Asia/Chita", - "Asia/Choibalsan", - "Asia/Chongqing", - "Asia/Chungking", - "Asia/Colombo", - "Asia/Dacca", - "Asia/Damascus", - "Asia/Dhaka", - "Asia/Dili", - "Asia/Dubai", - "Asia/Dushanbe", - "Asia/Famagusta", - "Asia/Gaza", - "Asia/Harbin", - "Asia/Hebron", - "Asia/Ho_Chi_Minh", - "Asia/Hong_Kong", - "Asia/Hovd", - "Asia/Irkutsk", - "Asia/Istanbul", - "Asia/Jakarta", - "Asia/Jayapura", - "Asia/Jerusalem", - "Asia/Kabul", - "Asia/Kamchatka", - "Asia/Karachi", - "Asia/Kashgar", - "Asia/Kathmandu", - "Asia/Katmandu", - "Asia/Khandyga", - "Asia/Kolkata", - "Asia/Krasnoyarsk", - "Asia/Kuala_Lumpur", - "Asia/Kuching", - "Asia/Kuwait", - "Asia/Macao", - "Asia/Macau", - "Asia/Magadan", - "Asia/Makassar", - "Asia/Manila", - "Asia/Muscat", - "Asia/Nicosia", - "Asia/Novokuznetsk", - "Asia/Novosibirsk", - "Asia/Omsk", - "Asia/Oral", - "Asia/Phnom_Penh", - "Asia/Pontianak", - "Asia/Pyongyang", - "Asia/Qatar", - "Asia/Qostanay", - "Asia/Qyzylorda", - "Asia/Rangoon", - "Asia/Riyadh", - "Asia/Saigon", - "Asia/Sakhalin", - "Asia/Samarkand", - "Asia/Seoul", - "Asia/Shanghai", - "Asia/Singapore", - "Asia/Srednekolymsk", - "Asia/Taipei", - "Asia/Tashkent", - "Asia/Tbilisi", - "Asia/Tehran", - "Asia/Tel_Aviv", - "Asia/Thimbu", - "Asia/Thimphu", - "Asia/Tokyo", - "Asia/Tomsk", - "Asia/Ujung_Pandang", - "Asia/Ulaanbaatar", - "Asia/Ulan_Bator", - "Asia/Urumqi", - "Asia/Ust-Nera", - "Asia/Vientiane", - "Asia/Vladivostok", - "Asia/Yakutsk", - "Asia/Yangon", - "Asia/Yekaterinburg", - "Asia/Yerevan", - "Atlantic/Azores", - "Atlantic/Bermuda", - "Atlantic/Canary", - "Atlantic/Cape_Verde", - "Atlantic/Faeroe", - "Atlantic/Faroe", - "Atlantic/Jan_Mayen", - "Atlantic/Madeira", - "Atlantic/Reykjavik", - "Atlantic/South_Georgia", - "Atlantic/St_Helena", - "Atlantic/Stanley", - "Australia/ACT", - "Australia/Adelaide", - "Australia/Brisbane", - "Australia/Broken_Hill", - "Australia/Canberra", - "Australia/Currie", - "Australia/Darwin", - "Australia/Eucla", - "Australia/Hobart", - "Australia/LHI", - "Australia/Lindeman", - "Australia/Lord_Howe", - "Australia/Melbourne", - "Australia/NSW", - "Australia/North", - "Australia/Perth", - "Australia/Queensland", - "Australia/South", - "Australia/Sydney", - "Australia/Tasmania", - "Australia/Victoria", - "Australia/West", - "Australia/Yancowinna", - "Brazil/Acre", - "Brazil/DeNoronha", - "Brazil/East", - "Brazil/West", - "CET", - "CST6CDT", - "Canada/Atlantic", - "Canada/Central", - "Canada/Eastern", - "Canada/Mountain", - "Canada/Newfoundland", - "Canada/Pacific", - "Canada/Saskatchewan", - "Canada/Yukon", - "Chile/Continental", - "Chile/EasterIsland", - "Cuba", - "EET", - "EST", - "EST5EDT", - "Egypt", - "Eire", - "Europe/Amsterdam", - "Europe/Andorra", - "Europe/Astrakhan", - "Europe/Athens", - "Europe/Belfast", - "Europe/Belgrade", - "Europe/Berlin", - "Europe/Bratislava", - "Europe/Brussels", - "Europe/Bucharest", - "Europe/Budapest", - "Europe/Busingen", - "Europe/Chisinau", - "Europe/Copenhagen", - "Europe/Dublin", - "Europe/Gibraltar", - "Europe/Guernsey", - "Europe/Helsinki", - "Europe/Isle_of_Man", - "Europe/Istanbul", - "Europe/Jersey", - "Europe/Kaliningrad", - "Europe/Kiev", - "Europe/Kirov", - "Europe/Lisbon", - "Europe/Ljubljana", - "Europe/London", - "Europe/Luxembourg", - "Europe/Madrid", - "Europe/Malta", - "Europe/Mariehamn", - "Europe/Minsk", - "Europe/Monaco", - "Europe/Moscow", - "Europe/Nicosia", - "Europe/Oslo", - "Europe/Paris", - "Europe/Podgorica", - "Europe/Prague", - "Europe/Riga", - "Europe/Rome", - "Europe/Samara", - "Europe/San_Marino", - "Europe/Sarajevo", - "Europe/Saratov", - "Europe/Simferopol", - "Europe/Skopje", - "Europe/Sofia", - "Europe/Stockholm", - "Europe/Tallinn", - "Europe/Tirane", - "Europe/Tiraspol", - "Europe/Ulyanovsk", - "Europe/Uzhgorod", - "Europe/Vaduz", - "Europe/Vatican", - "Europe/Vienna", - "Europe/Vilnius", - "Europe/Volgograd", - "Europe/Warsaw", - "Europe/Zagreb", - "Europe/Zaporozhye", - "Europe/Zurich", - "GB", - "GB-Eire", - "GMT", - "GMT+0", - "GMT-0", - "GMT0", - "Greenwich", - "HST", - "Hongkong", - "Iceland", - "Indian/Antananarivo", - "Indian/Chagos", - "Indian/Christmas", - "Indian/Cocos", - "Indian/Comoro", - "Indian/Kerguelen", - "Indian/Mahe", - "Indian/Maldives", - "Indian/Mauritius", - "Indian/Mayotte", - "Indian/Reunion", - "Iran", - "Israel", - "Jamaica", - "Japan", - "Kwajalein", - "Libya", - "MET", - "MST", - "MST7MDT", - "Mexico/BajaNorte", - "Mexico/BajaSur", - "Mexico/General", - "NZ", - "NZ-CHAT", - "Navajo", - "PRC", - "PST8PDT", - "Pacific/Apia", - "Pacific/Auckland", - "Pacific/Bougainville", - "Pacific/Chatham", - "Pacific/Chuuk", - "Pacific/Easter", - "Pacific/Efate", - "Pacific/Enderbury", - "Pacific/Fakaofo", - "Pacific/Fiji", - "Pacific/Funafuti", - "Pacific/Galapagos", - "Pacific/Gambier", - "Pacific/Guadalcanal", - "Pacific/Guam", - "Pacific/Honolulu", - "Pacific/Johnston", - "Pacific/Kiritimati", - "Pacific/Kosrae", - "Pacific/Kwajalein", - "Pacific/Majuro", - "Pacific/Marquesas", - "Pacific/Midway", - "Pacific/Nauru", - "Pacific/Niue", - "Pacific/Norfolk", - "Pacific/Noumea", - "Pacific/Pago_Pago", - "Pacific/Palau", - "Pacific/Pitcairn", - "Pacific/Pohnpei", - "Pacific/Ponape", - "Pacific/Port_Moresby", - "Pacific/Rarotonga", - "Pacific/Saipan", - "Pacific/Samoa", - "Pacific/Tahiti", - "Pacific/Tarawa", - "Pacific/Tongatapu", - "Pacific/Truk", - "Pacific/Wake", - "Pacific/Wallis", - "Pacific/Yap", - "Poland", - "Portugal", - "ROC", - "ROK", - "Singapore", - "Turkey", - "UCT", - "US/Alaska", - "US/Aleutian", - "US/Arizona", - "US/Central", - "US/East-Indiana", - "US/Eastern", - "US/Hawaii", - "US/Indiana-Starke", - "US/Michigan", - "US/Mountain", - "US/Pacific", - "US/Samoa", - "UTC", - "Universal", - "W-SU", - "WET", - "Zulu" - }; - for (String expectedTimezone : timezoneStrings) { - try { - final StandardSync actual = new StandardSync(); - // NOTE: this method call is the one that parses the given timezone string - // and will throw an exception if it isn't supported. This method is called - // on the API handler path. - ConnectionScheduleHelper.populateSyncFromScheduleTypeAndData(actual, - ConnectionScheduleType.CRON, new ConnectionScheduleData() - .cron(new ConnectionScheduleDataCron() - .cronTimeZone(expectedTimezone) - .cronExpression(EXPECTED_CRON_EXPRESSION))); - assertEquals(ScheduleType.CRON, actual.getScheduleType()); - assertEquals(expectedTimezone, actual.getScheduleData().getCron().getCronTimeZone()); - assertEquals(EXPECTED_CRON_EXPRESSION, actual.getScheduleData().getCron().getCronExpression()); - } catch (IllegalArgumentException | JsonValidationException e) { - throw (RuntimeException) new RuntimeException( - "One of the timezones is not supported - update airbyte-webapp/src/config/availableCronTimeZones.json!") - .initCause(e); - } - } - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionsHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionsHandlerTest.java deleted file mode 100644 index d595489c6be00..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/ConnectionsHandlerTest.java +++ /dev/null @@ -1,1377 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static io.airbyte.commons.server.helpers.ConnectionHelpers.FIELD_NAME; -import static io.airbyte.commons.server.helpers.ConnectionHelpers.SECOND_FIELD_NAME; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.common.collect.Lists; -import io.airbyte.analytics.TrackingClient; -import io.airbyte.api.model.generated.AirbyteCatalog; -import io.airbyte.api.model.generated.AirbyteStream; -import io.airbyte.api.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.model.generated.AirbyteStreamConfiguration; -import io.airbyte.api.model.generated.ConnectionCreate; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; -import io.airbyte.api.model.generated.ConnectionSchedule; -import io.airbyte.api.model.generated.ConnectionScheduleData; -import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; -import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule.TimeUnitEnum; -import io.airbyte.api.model.generated.ConnectionScheduleDataCron; -import io.airbyte.api.model.generated.ConnectionScheduleType; -import io.airbyte.api.model.generated.ConnectionSearch; -import io.airbyte.api.model.generated.ConnectionStatus; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.DestinationSearch; -import io.airbyte.api.model.generated.DestinationSyncMode; -import io.airbyte.api.model.generated.NamespaceDefinitionType; -import io.airbyte.api.model.generated.ResourceRequirements; -import io.airbyte.api.model.generated.SelectedFieldInfo; -import io.airbyte.api.model.generated.SourceSearch; -import io.airbyte.api.model.generated.StreamDescriptor; -import io.airbyte.api.model.generated.SyncMode; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.helpers.ConnectionHelpers; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.config.BasicSchedule; -import io.airbyte.config.ConfigSchema; -import io.airbyte.config.Cron; -import io.airbyte.config.DataType; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.FieldSelectionData; -import io.airbyte.config.Geography; -import io.airbyte.config.JobSyncConfig; -import io.airbyte.config.Schedule; -import io.airbyte.config.Schedule.TimeUnit; -import io.airbyte.config.ScheduleData; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.ScheduleType; -import io.airbyte.config.StandardSync.Status; -import io.airbyte.config.StandardWorkspace; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.WorkspaceHelper; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.validation.json.JsonValidationException; -import io.airbyte.workers.helper.ConnectionHelper; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.function.Supplier; -import org.assertj.core.api.Assertions; -import org.junit.Assert; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -class ConnectionsHandlerTest { - - private ConfigRepository configRepository; - private Supplier uuidGenerator; - - private ConnectionsHandler connectionsHandler; - private UUID workspaceId; - private UUID sourceId; - private UUID destinationId; - - private SourceConnection source; - private DestinationConnection destination; - private StandardSync standardSync; - private StandardSync standardSyncDeleted; - private UUID connectionId; - private UUID operationId; - private UUID otherOperationId; - private WorkspaceHelper workspaceHelper; - private TrackingClient trackingClient; - private EventRunner eventRunner; - private ConnectionHelper connectionHelper; - - private static final String PRESTO_TO_HUDI = "presto to hudi"; - private static final String PRESTO_TO_HUDI_PREFIX = "presto_to_hudi"; - private static final String SOURCE_TEST = "source-test"; - private static final String DESTINATION_TEST = "destination-test"; - private static final String CURSOR1 = "cursor1"; - private static final String CURSOR2 = "cursor2"; - private static final String PK1 = "pk1"; - private static final String PK2 = "pk2"; - private static final String PK3 = "pk3"; - private static final String STREAM1 = "stream1"; - private static final String STREAM2 = "stream2"; - private static final String AZKABAN_USERS = "azkaban_users"; - private final static String CRON_TIMEZONE_UTC = "UTC"; - private final static String CRON_EXPRESSION = "* */2 * * * ?"; - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() throws IOException, JsonValidationException, ConfigNotFoundException { - - workspaceId = UUID.randomUUID(); - sourceId = UUID.randomUUID(); - destinationId = UUID.randomUUID(); - connectionId = UUID.randomUUID(); - operationId = UUID.randomUUID(); - otherOperationId = UUID.randomUUID(); - source = new SourceConnection() - .withSourceId(sourceId) - .withWorkspaceId(workspaceId) - .withName("presto"); - destination = new DestinationConnection() - .withDestinationId(destinationId) - .withWorkspaceId(workspaceId) - .withName("hudi") - .withConfiguration(Jsons.jsonNode(Collections.singletonMap("apiKey", "123-abc"))); - standardSync = new StandardSync() - .withConnectionId(connectionId) - .withName(PRESTO_TO_HUDI) - .withNamespaceDefinition(JobSyncConfig.NamespaceDefinitionType.SOURCE) - .withNamespaceFormat(null) - .withPrefix(PRESTO_TO_HUDI_PREFIX) - .withStatus(StandardSync.Status.ACTIVE) - .withCatalog(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()) - .withFieldSelectionData(new FieldSelectionData().withAdditionalProperty("null/users-data0", false)) - .withSourceId(sourceId) - .withDestinationId(destinationId) - .withOperationIds(List.of(operationId)) - .withManual(false) - .withSchedule(ConnectionHelpers.generateBasicSchedule()) - .withScheduleType(ScheduleType.BASIC_SCHEDULE) - .withScheduleData(ConnectionHelpers.generateBasicScheduleData()) - .withResourceRequirements(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS) - .withSourceCatalogId(UUID.randomUUID()) - .withGeography(Geography.AUTO) - .withBreakingChange(false); - standardSyncDeleted = new StandardSync() - .withConnectionId(connectionId) - .withName("presto to hudi2") - .withNamespaceDefinition(JobSyncConfig.NamespaceDefinitionType.SOURCE) - .withNamespaceFormat(null) - .withPrefix("presto_to_hudi2") - .withStatus(StandardSync.Status.DEPRECATED) - .withCatalog(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()) - .withSourceId(sourceId) - .withDestinationId(destinationId) - .withOperationIds(List.of(operationId)) - .withManual(false) - .withSchedule(ConnectionHelpers.generateBasicSchedule()) - .withResourceRequirements(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS) - .withGeography(Geography.US); - - configRepository = mock(ConfigRepository.class); - uuidGenerator = mock(Supplier.class); - workspaceHelper = mock(WorkspaceHelper.class); - trackingClient = mock(TrackingClient.class); - eventRunner = mock(EventRunner.class); - connectionHelper = mock(ConnectionHelper.class); - when(workspaceHelper.getWorkspaceForSourceIdIgnoreExceptions(sourceId)).thenReturn(workspaceId); - when(workspaceHelper.getWorkspaceForDestinationIdIgnoreExceptions(destinationId)).thenReturn(workspaceId); - when(workspaceHelper.getWorkspaceForOperationIdIgnoreExceptions(operationId)).thenReturn(workspaceId); - when(workspaceHelper.getWorkspaceForOperationIdIgnoreExceptions(otherOperationId)).thenReturn(workspaceId); - } - - @Nested - class UnMockedConnectionHelper { - - @BeforeEach - void setUp() throws JsonValidationException, ConfigNotFoundException, IOException { - connectionsHandler = new ConnectionsHandler( - configRepository, - uuidGenerator, - workspaceHelper, - trackingClient, - eventRunner, - connectionHelper); - - when(uuidGenerator.get()).thenReturn(standardSync.getConnectionId()); - final StandardSourceDefinition sourceDefinition = new StandardSourceDefinition() - .withName(SOURCE_TEST) - .withSourceDefinitionId(UUID.randomUUID()); - final StandardDestinationDefinition destinationDefinition = new StandardDestinationDefinition() - .withName(DESTINATION_TEST) - .withDestinationDefinitionId(UUID.randomUUID()); - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - when(configRepository.getSourceDefinitionFromConnection(standardSync.getConnectionId())).thenReturn( - sourceDefinition); - when(configRepository.getDestinationDefinitionFromConnection(standardSync.getConnectionId())).thenReturn( - destinationDefinition); - when(configRepository.getSourceConnection(source.getSourceId())) - .thenReturn(source); - when(configRepository.getDestinationConnection(destination.getDestinationId())) - .thenReturn(destination); - } - - @Nested - class CreateConnection { - - private ConnectionCreate buildConnectionCreateRequest(final StandardSync standardSync, final AirbyteCatalog catalog) { - return new ConnectionCreate() - .sourceId(standardSync.getSourceId()) - .destinationId(standardSync.getDestinationId()) - .operationIds(standardSync.getOperationIds()) - .name(PRESTO_TO_HUDI) - .namespaceDefinition(NamespaceDefinitionType.SOURCE) - .namespaceFormat(null) - .prefix(PRESTO_TO_HUDI_PREFIX) - .status(ConnectionStatus.ACTIVE) - .schedule(ConnectionHelpers.generateBasicConnectionSchedule()) - .syncCatalog(catalog) - .resourceRequirements(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(standardSync.getResourceRequirements().getCpuRequest()) - .cpuLimit(standardSync.getResourceRequirements().getCpuLimit()) - .memoryRequest(standardSync.getResourceRequirements().getMemoryRequest()) - .memoryLimit(standardSync.getResourceRequirements().getMemoryLimit())) - .sourceCatalogId(standardSync.getSourceCatalogId()) - .geography(ApiPojoConverters.toApiGeography(standardSync.getGeography())); - } - - @Test - void testCreateConnection() throws JsonValidationException, ConfigNotFoundException, IOException { - - final AirbyteCatalog catalog = ConnectionHelpers.generateBasicApiCatalog(); - - // set a defaultGeography on the workspace as EU, but expect connection to be - // created AUTO because the ConnectionCreate geography takes precedence over the workspace - // defaultGeography. - final StandardWorkspace workspace = new StandardWorkspace() - .withWorkspaceId(workspaceId) - .withDefaultGeography(Geography.EU); - when(configRepository.getStandardWorkspaceNoSecrets(workspaceId, true)).thenReturn(workspace); - - final ConnectionCreate connectionCreate = buildConnectionCreateRequest(standardSync, catalog); - - final ConnectionRead actualConnectionRead = connectionsHandler.createConnection(connectionCreate); - - final ConnectionRead expectedConnectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - - assertEquals(expectedConnectionRead, actualConnectionRead); - - verify(configRepository).writeStandardSync(standardSync); - - // Use new schedule schema, verify that we get the same results. - connectionCreate - .schedule(null) - .scheduleType(ConnectionScheduleType.BASIC) - .scheduleData(ConnectionHelpers.generateBasicConnectionScheduleData()); - assertEquals(expectedConnectionRead, connectionsHandler.createConnection(connectionCreate)); - } - - @Test - void testCreateConnectionUsesDefaultGeographyFromWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - - when(workspaceHelper.getWorkspaceForSourceId(sourceId)).thenReturn(workspaceId); - - final AirbyteCatalog catalog = ConnectionHelpers.generateBasicApiCatalog(); - - // don't set a geography on the ConnectionCreate to force inheritance from workspace default - final ConnectionCreate connectionCreate = buildConnectionCreateRequest(standardSync, catalog).geography(null); - - // set the workspace default to EU - final StandardWorkspace workspace = new StandardWorkspace() - .withWorkspaceId(workspaceId) - .withDefaultGeography(Geography.EU); - when(configRepository.getStandardWorkspaceNoSecrets(workspaceId, true)).thenReturn(workspace); - - // the expected read and verified write is generated from the standardSync, so set this to EU as - // well - standardSync.setGeography(Geography.EU); - - final ConnectionRead expectedConnectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - final ConnectionRead actualConnectionRead = connectionsHandler.createConnection(connectionCreate); - - assertEquals(expectedConnectionRead, actualConnectionRead); - verify(configRepository).writeStandardSync(standardSync); - } - - @Test - void testCreateConnectionWithSelectedFields() throws IOException, JsonValidationException, ConfigNotFoundException { - final StandardWorkspace workspace = new StandardWorkspace() - .withWorkspaceId(workspaceId) - .withDefaultGeography(Geography.AUTO); - when(configRepository.getStandardWorkspaceNoSecrets(workspaceId, true)).thenReturn(workspace); - - final AirbyteCatalog catalogWithSelectedFields = ConnectionHelpers.generateApiCatalogWithTwoFields(); - // Only select one of the two fields. - catalogWithSelectedFields.getStreams().get(0).getConfig().fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME))); - - final ConnectionCreate connectionCreate = buildConnectionCreateRequest(standardSync, catalogWithSelectedFields); - - final ConnectionRead actualConnectionRead = connectionsHandler.createConnection(connectionCreate); - - final ConnectionRead expectedConnectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - - assertEquals(expectedConnectionRead, actualConnectionRead); - - standardSync.withFieldSelectionData(new FieldSelectionData().withAdditionalProperty("null/users-data0", true)); - - verify(configRepository).writeStandardSync(standardSync); - } - - @Test - void testCreateFullRefreshConnectionWithSelectedFields() throws IOException, JsonValidationException, ConfigNotFoundException { - final StandardWorkspace workspace = new StandardWorkspace() - .withWorkspaceId(workspaceId) - .withDefaultGeography(Geography.AUTO); - when(configRepository.getStandardWorkspaceNoSecrets(workspaceId, true)).thenReturn(workspace); - - final AirbyteCatalog fullRefreshCatalogWithSelectedFields = ConnectionHelpers.generateApiCatalogWithTwoFields(); - fullRefreshCatalogWithSelectedFields.getStreams().get(0).getConfig() - .fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME))) - .cursorField(null) - .syncMode(SyncMode.FULL_REFRESH); - - final ConnectionCreate connectionCreate = buildConnectionCreateRequest(standardSync, fullRefreshCatalogWithSelectedFields); - - final ConnectionRead actualConnectionRead = connectionsHandler.createConnection(connectionCreate); - - final ConnectionRead expectedConnectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - - assertEquals(expectedConnectionRead, actualConnectionRead); - - standardSync - .withFieldSelectionData(new FieldSelectionData().withAdditionalProperty("null/users-data0", true)) - .getCatalog().getStreams().get(0).withSyncMode(io.airbyte.protocol.models.SyncMode.FULL_REFRESH).withCursorField(null); - - verify(configRepository).writeStandardSync(standardSync); - } - - @Test - void testFieldSelectionRemoveCursorFails() throws JsonValidationException, ConfigNotFoundException, IOException { - // Test that if we try to de-select a field that's being used for the cursor, the request will fail. - // The connection initially has a catalog with one stream, and two fields in that stream. - standardSync.setCatalog(ConnectionHelpers.generateAirbyteCatalogWithTwoFields()); - - // Send an update that sets a cursor but de-selects that field. - final AirbyteCatalog catalogForUpdate = ConnectionHelpers.generateApiCatalogWithTwoFields(); - catalogForUpdate.getStreams().get(0).getConfig() - .fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME))) - .cursorField(List.of(SECOND_FIELD_NAME)) - .syncMode(SyncMode.INCREMENTAL); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .syncCatalog(catalogForUpdate); - - assertThrows(JsonValidationException.class, () -> connectionsHandler.updateConnection(connectionUpdate)); - } - - @Test - void testFieldSelectionRemovePrimaryKeyFails() throws JsonValidationException, ConfigNotFoundException, IOException { - // Test that if we try to de-select a field that's being used for the primary key, the request will - // fail. - // The connection initially has a catalog with one stream, and two fields in that stream. - standardSync.setCatalog(ConnectionHelpers.generateAirbyteCatalogWithTwoFields()); - - // Send an update that sets a primary key but deselects that field. - final AirbyteCatalog catalogForUpdate = ConnectionHelpers.generateApiCatalogWithTwoFields(); - catalogForUpdate.getStreams().get(0).getConfig() - .fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME))) - .destinationSyncMode(DestinationSyncMode.APPEND_DEDUP) - .primaryKey(List.of(List.of(SECOND_FIELD_NAME))); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .syncCatalog(catalogForUpdate); - - assertThrows(JsonValidationException.class, () -> connectionsHandler.updateConnection(connectionUpdate)); - } - - @Test - void testValidateConnectionCreateSourceAndDestinationInDifferenceWorkspace() { - - when(workspaceHelper.getWorkspaceForDestinationIdIgnoreExceptions(destinationId)).thenReturn(UUID.randomUUID()); - - final ConnectionCreate connectionCreate = new ConnectionCreate() - .sourceId(standardSync.getSourceId()) - .destinationId(standardSync.getDestinationId()); - - assertThrows(IllegalArgumentException.class, () -> connectionsHandler.createConnection(connectionCreate)); - } - - @Test - void testValidateConnectionCreateOperationInDifferentWorkspace() { - - when(workspaceHelper.getWorkspaceForOperationIdIgnoreExceptions(operationId)).thenReturn(UUID.randomUUID()); - - final ConnectionCreate connectionCreate = new ConnectionCreate() - .sourceId(standardSync.getSourceId()) - .destinationId(standardSync.getDestinationId()) - .operationIds(Collections.singletonList(operationId)); - - assertThrows(IllegalArgumentException.class, () -> connectionsHandler.createConnection(connectionCreate)); - } - - @Test - void testCreateConnectionWithBadDefinitionIds() throws JsonValidationException, ConfigNotFoundException, IOException { - - final UUID sourceIdBad = UUID.randomUUID(); - final UUID destinationIdBad = UUID.randomUUID(); - - when(configRepository.getSourceConnection(sourceIdBad)) - .thenThrow(new ConfigNotFoundException(ConfigSchema.SOURCE_CONNECTION, sourceIdBad)); - when(configRepository.getDestinationConnection(destinationIdBad)) - .thenThrow(new ConfigNotFoundException(ConfigSchema.DESTINATION_CONNECTION, destinationIdBad)); - - final AirbyteCatalog catalog = ConnectionHelpers.generateBasicApiCatalog(); - - final ConnectionCreate connectionCreateBadSource = new ConnectionCreate() - .sourceId(sourceIdBad) - .destinationId(standardSync.getDestinationId()) - .operationIds(standardSync.getOperationIds()) - .name(PRESTO_TO_HUDI) - .namespaceDefinition(NamespaceDefinitionType.SOURCE) - .namespaceFormat(null) - .prefix(PRESTO_TO_HUDI_PREFIX) - .status(ConnectionStatus.ACTIVE) - .schedule(ConnectionHelpers.generateBasicConnectionSchedule()) - .syncCatalog(catalog); - - assertThrows(ConfigNotFoundException.class, () -> connectionsHandler.createConnection(connectionCreateBadSource)); - - final ConnectionCreate connectionCreateBadDestination = new ConnectionCreate() - .sourceId(standardSync.getSourceId()) - .destinationId(destinationIdBad) - .operationIds(standardSync.getOperationIds()) - .name(PRESTO_TO_HUDI) - .namespaceDefinition(NamespaceDefinitionType.SOURCE) - .namespaceFormat(null) - .prefix(PRESTO_TO_HUDI_PREFIX) - .status(ConnectionStatus.ACTIVE) - .schedule(ConnectionHelpers.generateBasicConnectionSchedule()) - .syncCatalog(catalog); - - assertThrows(ConfigNotFoundException.class, () -> connectionsHandler.createConnection(connectionCreateBadDestination)); - - } - - } - - @Nested - class UpdateConnection { - - @Test - void testUpdateConnectionPatchSingleField() throws Exception { - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .name("newName"); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .name("newName"); - final StandardSync expectedPersistedSync = Jsons.clone(standardSync).withName("newName"); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchScheduleToManual() throws Exception { - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .scheduleType(ConnectionScheduleType.MANUAL); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .schedule(null) - .scheduleType(ConnectionScheduleType.MANUAL) - .scheduleData(null); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withSchedule(null) - .withScheduleType(ScheduleType.MANUAL) - .withScheduleData(null) - .withManual(true); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchScheduleToCron() throws Exception { - - final ConnectionScheduleData cronScheduleData = new ConnectionScheduleData().cron( - new ConnectionScheduleDataCron().cronExpression(CRON_EXPRESSION).cronTimeZone(CRON_TIMEZONE_UTC)); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .scheduleType(ConnectionScheduleType.CRON) - .scheduleData(cronScheduleData); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .schedule(null) - .scheduleType(ConnectionScheduleType.CRON) - .scheduleData(cronScheduleData); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withSchedule(null) - .withScheduleType(ScheduleType.CRON) - .withScheduleData(new ScheduleData().withCron(new Cron().withCronExpression(CRON_EXPRESSION).withCronTimeZone(CRON_TIMEZONE_UTC))) - .withManual(false); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchBasicSchedule() throws Exception { - - final ConnectionScheduleData newScheduleData = - new ConnectionScheduleData().basicSchedule(new ConnectionScheduleDataBasicSchedule().timeUnit(TimeUnitEnum.DAYS).units(10L)); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .scheduleType(ConnectionScheduleType.BASIC) // update route requires this to be set even if it isn't changing - .scheduleData(newScheduleData); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .schedule(new ConnectionSchedule().timeUnit(ConnectionSchedule.TimeUnitEnum.DAYS).units(10L)) // still dual-writing to legacy field - .scheduleType(ConnectionScheduleType.BASIC) - .scheduleData(newScheduleData); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withSchedule(new Schedule().withTimeUnit(TimeUnit.DAYS).withUnits(10L)) // still dual-writing to legacy field - .withScheduleType(ScheduleType.BASIC_SCHEDULE) - .withScheduleData(new ScheduleData().withBasicSchedule(new BasicSchedule().withTimeUnit(BasicSchedule.TimeUnit.DAYS).withUnits(10L))) - .withManual(false); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchAddingNewStream() throws Exception { - // the connection initially has a catalog with one stream. this test generates another catalog with - // one stream, changes that stream's name to something new, and sends both streams in the patch - // request. - // the test expects the final result to include both streams. - final AirbyteCatalog catalogWithNewStream = ConnectionHelpers.generateBasicApiCatalog(); - catalogWithNewStream.getStreams().get(0).getStream().setName(AZKABAN_USERS); - catalogWithNewStream.getStreams().get(0).getConfig().setAliasName(AZKABAN_USERS); - - final AirbyteCatalog catalogForUpdate = ConnectionHelpers.generateMultipleStreamsApiCatalog(2); - catalogForUpdate.getStreams().get(1).getStream().setName(AZKABAN_USERS); - catalogForUpdate.getStreams().get(1).getConfig().setAliasName(AZKABAN_USERS); - - // expect two streams in the final persisted catalog -- the original unchanged stream, plus the new - // AZKABAN_USERS stream - - final ConfiguredAirbyteCatalog expectedPersistedCatalog = ConnectionHelpers.generateMultipleStreamsConfiguredAirbyteCatalog(2); - expectedPersistedCatalog.getStreams().get(1).getStream().setName(AZKABAN_USERS); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .syncCatalog(catalogForUpdate); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .syncCatalog(catalogForUpdate); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withCatalog(expectedPersistedCatalog) - .withFieldSelectionData(CatalogConverter.getFieldSelectionData(catalogForUpdate)); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchEditExistingStreamWhileAddingNewStream() throws Exception { - // the connection initially has a catalog with two streams. this test updates the catalog - // with a sync mode change for one of the initial streams while also adding a brand-new - // stream. The result should be a catalog with three streams. - standardSync.setCatalog(ConnectionHelpers.generateMultipleStreamsConfiguredAirbyteCatalog(2)); - - final AirbyteCatalog catalogForUpdate = ConnectionHelpers.generateMultipleStreamsApiCatalog(3); - catalogForUpdate.getStreams().get(0).getConfig().setSyncMode(SyncMode.FULL_REFRESH); - catalogForUpdate.getStreams().get(2).getStream().setName(AZKABAN_USERS); - catalogForUpdate.getStreams().get(2).getConfig().setAliasName(AZKABAN_USERS); - - // expect three streams in the final persisted catalog - final ConfiguredAirbyteCatalog expectedPersistedCatalog = ConnectionHelpers.generateMultipleStreamsConfiguredAirbyteCatalog(3); - expectedPersistedCatalog.getStreams().get(0).withSyncMode(io.airbyte.protocol.models.SyncMode.FULL_REFRESH); - // index 1 is unchanged - expectedPersistedCatalog.getStreams().get(2).getStream().withName(AZKABAN_USERS); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .syncCatalog(catalogForUpdate); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .syncCatalog(catalogForUpdate); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withCatalog(expectedPersistedCatalog) - .withFieldSelectionData(CatalogConverter.getFieldSelectionData(catalogForUpdate)); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchColumnSelection() throws Exception { - // The connection initially has a catalog with one stream, and two fields in that stream. - standardSync.setCatalog(ConnectionHelpers.generateAirbyteCatalogWithTwoFields()); - - // Send an update that only selects one of the fields. - final AirbyteCatalog catalogForUpdate = ConnectionHelpers.generateApiCatalogWithTwoFields(); - catalogForUpdate.getStreams().get(0).getConfig().fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem(FIELD_NAME))); - - // Expect one column in the final persisted catalog - final ConfiguredAirbyteCatalog expectedPersistedCatalog = ConnectionHelpers.generateBasicConfiguredAirbyteCatalog(); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .syncCatalog(catalogForUpdate); - - final ConnectionRead expectedRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync) - .syncCatalog(catalogForUpdate); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withCatalog(expectedPersistedCatalog) - .withFieldSelectionData(CatalogConverter.getFieldSelectionData(catalogForUpdate)); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - assertEquals(expectedRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testUpdateConnectionPatchingSeveralFieldsAndReplaceAStream() throws JsonValidationException, ConfigNotFoundException, IOException { - final AirbyteCatalog catalogForUpdate = ConnectionHelpers.generateMultipleStreamsApiCatalog(2); - - // deselect the existing stream, and add a new stream called 'azkaban_users'. - // result that we persist and read after update should be a catalog with a single - // stream called 'azkaban_users'. - catalogForUpdate.getStreams().get(0).getConfig().setSelected(false); - catalogForUpdate.getStreams().get(1).getStream().setName(AZKABAN_USERS); - catalogForUpdate.getStreams().get(1).getConfig().setAliasName(AZKABAN_USERS); - - final UUID newSourceCatalogId = UUID.randomUUID(); - - final ResourceRequirements resourceRequirements = new ResourceRequirements() - .cpuLimit(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getCpuLimit()) - .cpuRequest(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getCpuRequest()) - .memoryLimit(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getMemoryLimit()) - .memoryRequest(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getMemoryRequest()); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .status(ConnectionStatus.INACTIVE) - .scheduleType(ConnectionScheduleType.MANUAL) - .syncCatalog(catalogForUpdate) - .resourceRequirements(resourceRequirements) - .sourceCatalogId(newSourceCatalogId) - .operationIds(List.of(operationId, otherOperationId)) - .geography(io.airbyte.api.model.generated.Geography.EU); - - final ConfiguredAirbyteCatalog expectedPersistedCatalog = ConnectionHelpers.generateBasicConfiguredAirbyteCatalog(); - expectedPersistedCatalog.getStreams().get(0).getStream().withName(AZKABAN_USERS); - - final StandardSync expectedPersistedSync = Jsons.clone(standardSync) - .withStatus(Status.INACTIVE) - .withScheduleType(ScheduleType.MANUAL) - .withScheduleData(null) - .withSchedule(null) - .withManual(true) - .withCatalog(expectedPersistedCatalog) - .withFieldSelectionData(CatalogConverter.getFieldSelectionData(catalogForUpdate)) - .withResourceRequirements(ApiPojoConverters.resourceRequirementsToInternal(resourceRequirements)) - .withSourceCatalogId(newSourceCatalogId) - .withOperationIds(List.of(operationId, otherOperationId)) - .withGeography(Geography.EU); - - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.updateConnection(connectionUpdate); - - final AirbyteCatalog expectedCatalogInRead = ConnectionHelpers.generateBasicApiCatalog(); - expectedCatalogInRead.getStreams().get(0).getStream().setName(AZKABAN_USERS); - expectedCatalogInRead.getStreams().get(0).getConfig().setAliasName(AZKABAN_USERS); - - final ConnectionRead expectedConnectionRead = ConnectionHelpers.generateExpectedConnectionRead( - standardSync.getConnectionId(), - standardSync.getSourceId(), - standardSync.getDestinationId(), - standardSync.getOperationIds(), - newSourceCatalogId, - ApiPojoConverters.toApiGeography(standardSync.getGeography()), false) - .status(ConnectionStatus.INACTIVE) - .scheduleType(ConnectionScheduleType.MANUAL) - .scheduleData(null) - .schedule(null) - .syncCatalog(expectedCatalogInRead) - .resourceRequirements(resourceRequirements); - - assertEquals(expectedConnectionRead, actualConnectionRead); - verify(configRepository).writeStandardSync(expectedPersistedSync); - verify(eventRunner).update(connectionUpdate.getConnectionId()); - } - - @Test - void testValidateConnectionUpdateOperationInDifferentWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - when(workspaceHelper.getWorkspaceForOperationIdIgnoreExceptions(operationId)).thenReturn(UUID.randomUUID()); - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - - final ConnectionUpdate connectionUpdate = new ConnectionUpdate() - .connectionId(standardSync.getConnectionId()) - .operationIds(Collections.singletonList(operationId)) - .syncCatalog(CatalogConverter.toApi(standardSync.getCatalog(), standardSync.getFieldSelectionData())); - - assertThrows(IllegalArgumentException.class, () -> connectionsHandler.updateConnection(connectionUpdate)); - } - - } - - @Test - void testGetConnection() throws JsonValidationException, ConfigNotFoundException, IOException { - when(configRepository.getStandardSync(standardSync.getConnectionId())) - .thenReturn(standardSync); - - final ConnectionRead actualConnectionRead = connectionsHandler.getConnection(standardSync.getConnectionId()); - - assertEquals(ConnectionHelpers.generateExpectedConnectionRead(standardSync), actualConnectionRead); - } - - @Test - void testListConnectionsForWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - when(configRepository.listWorkspaceStandardSyncs(source.getWorkspaceId(), false)) - .thenReturn(Lists.newArrayList(standardSync)); - when(configRepository.listWorkspaceStandardSyncs(source.getWorkspaceId(), true)) - .thenReturn(Lists.newArrayList(standardSync, standardSyncDeleted)); - when(configRepository.getStandardSync(standardSync.getConnectionId())) - .thenReturn(standardSync); - - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(source.getWorkspaceId()); - final ConnectionReadList actualConnectionReadList = connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals( - ConnectionHelpers.generateExpectedConnectionRead(standardSync), - actualConnectionReadList.getConnections().get(0)); - - final ConnectionReadList actualConnectionReadListWithDeleted = connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody, true); - final List connections = actualConnectionReadListWithDeleted.getConnections(); - assertEquals(2, connections.size()); - assertEquals(ApiPojoConverters.internalToConnectionRead(standardSync), connections.get(0)); - assertEquals(ApiPojoConverters.internalToConnectionRead(standardSyncDeleted), connections.get(1)); - - } - - @Test - void testListConnections() throws JsonValidationException, ConfigNotFoundException, IOException { - when(configRepository.listStandardSyncs()) - .thenReturn(Lists.newArrayList(standardSync)); - when(configRepository.getSourceConnection(source.getSourceId())) - .thenReturn(source); - when(configRepository.getStandardSync(standardSync.getConnectionId())) - .thenReturn(standardSync); - - final ConnectionReadList actualConnectionReadList = connectionsHandler.listConnections(); - - assertEquals( - ConnectionHelpers.generateExpectedConnectionRead(standardSync), - actualConnectionReadList.getConnections().get(0)); - } - - @Test - void testSearchConnections() throws JsonValidationException, ConfigNotFoundException, IOException { - final ConnectionRead connectionRead1 = ConnectionHelpers.connectionReadFromStandardSync(standardSync); - final StandardSync standardSync2 = new StandardSync() - .withConnectionId(UUID.randomUUID()) - .withName("test connection") - .withNamespaceDefinition(JobSyncConfig.NamespaceDefinitionType.CUSTOMFORMAT) - .withNamespaceFormat("ns_format") - .withPrefix("test_prefix") - .withStatus(StandardSync.Status.ACTIVE) - .withCatalog(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()) - .withSourceId(sourceId) - .withDestinationId(destinationId) - .withOperationIds(List.of(operationId)) - .withManual(true) - .withResourceRequirements(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS) - .withGeography(Geography.US) - .withBreakingChange(false); - final ConnectionRead connectionRead2 = ConnectionHelpers.connectionReadFromStandardSync(standardSync2); - final StandardSourceDefinition sourceDefinition = new StandardSourceDefinition() - .withName(SOURCE_TEST) - .withSourceDefinitionId(UUID.randomUUID()); - final StandardDestinationDefinition destinationDefinition = new StandardDestinationDefinition() - .withName(DESTINATION_TEST) - .withDestinationDefinitionId(UUID.randomUUID()); - - when(configRepository.listStandardSyncs()) - .thenReturn(Lists.newArrayList(standardSync, standardSync2)); - when(configRepository.getSourceConnection(source.getSourceId())) - .thenReturn(source); - when(configRepository.getDestinationConnection(destination.getDestinationId())) - .thenReturn(destination); - when(configRepository.getStandardSync(standardSync.getConnectionId())) - .thenReturn(standardSync); - when(configRepository.getStandardSync(standardSync2.getConnectionId())) - .thenReturn(standardSync2); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - when(configRepository.getStandardDestinationDefinition(destination.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - - final ConnectionSearch connectionSearch = new ConnectionSearch(); - connectionSearch.namespaceDefinition(NamespaceDefinitionType.SOURCE); - ConnectionReadList actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - - connectionSearch.namespaceDefinition(null); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(2, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(1)); - - final SourceSearch sourceSearch = new SourceSearch().sourceId(UUID.randomUUID()); - connectionSearch.setSource(sourceSearch); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(0, actualConnectionReadList.getConnections().size()); - - sourceSearch.sourceId(connectionRead1.getSourceId()); - connectionSearch.setSource(sourceSearch); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(2, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(1)); - - final DestinationSearch destinationSearch = new DestinationSearch(); - connectionSearch.setDestination(destinationSearch); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(2, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(1)); - - destinationSearch.connectionConfiguration(Jsons.jsonNode(Collections.singletonMap("apiKey", "not-found"))); - connectionSearch.setDestination(destinationSearch); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(0, actualConnectionReadList.getConnections().size()); - - destinationSearch.connectionConfiguration(Jsons.jsonNode(Collections.singletonMap("apiKey", "123-abc"))); - connectionSearch.setDestination(destinationSearch); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(2, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(1)); - - connectionSearch.name("non-existent"); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(0, actualConnectionReadList.getConnections().size()); - - connectionSearch.name(connectionRead1.getName()); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - - connectionSearch.name(connectionRead2.getName()); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(0)); - - connectionSearch.namespaceDefinition(connectionRead1.getNamespaceDefinition()); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(0, actualConnectionReadList.getConnections().size()); - - connectionSearch.name(null); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - - connectionSearch.namespaceDefinition(connectionRead2.getNamespaceDefinition()); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(0)); - - connectionSearch.namespaceDefinition(null); - connectionSearch.status(ConnectionStatus.INACTIVE); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(0, actualConnectionReadList.getConnections().size()); - - connectionSearch.status(ConnectionStatus.ACTIVE); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(2, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(1)); - - connectionSearch.prefix(connectionRead1.getPrefix()); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead1, actualConnectionReadList.getConnections().get(0)); - - connectionSearch.prefix(connectionRead2.getPrefix()); - actualConnectionReadList = connectionsHandler.searchConnections(connectionSearch); - assertEquals(1, actualConnectionReadList.getConnections().size()); - assertEquals(connectionRead2, actualConnectionReadList.getConnections().get(0)); - } - - @Test - void testDeleteConnection() throws JsonValidationException, ConfigNotFoundException, IOException { - connectionsHandler.deleteConnection(connectionId); - - verify(connectionHelper).deleteConnection(connectionId); - } - - @Test - void failOnUnmatchedWorkspacesInCreate() throws JsonValidationException, ConfigNotFoundException, IOException { - when(workspaceHelper.getWorkspaceForSourceIdIgnoreExceptions(standardSync.getSourceId())).thenReturn(UUID.randomUUID()); - when(workspaceHelper.getWorkspaceForDestinationIdIgnoreExceptions(standardSync.getDestinationId())).thenReturn(UUID.randomUUID()); - when(configRepository.getSourceConnection(source.getSourceId())) - .thenReturn(source); - when(configRepository.getDestinationConnection(destination.getDestinationId())) - .thenReturn(destination); - - when(uuidGenerator.get()).thenReturn(standardSync.getConnectionId()); - final StandardSourceDefinition sourceDefinition = new StandardSourceDefinition() - .withName(SOURCE_TEST) - .withSourceDefinitionId(UUID.randomUUID()); - final StandardDestinationDefinition destinationDefinition = new StandardDestinationDefinition() - .withName(DESTINATION_TEST) - .withDestinationDefinitionId(UUID.randomUUID()); - when(configRepository.getStandardSync(standardSync.getConnectionId())).thenReturn(standardSync); - when(configRepository.getSourceDefinitionFromConnection(standardSync.getConnectionId())).thenReturn(sourceDefinition); - when(configRepository.getDestinationDefinitionFromConnection(standardSync.getConnectionId())).thenReturn(destinationDefinition); - - final AirbyteCatalog catalog = ConnectionHelpers.generateBasicApiCatalog(); - - final ConnectionCreate connectionCreate = new ConnectionCreate() - .sourceId(standardSync.getSourceId()) - .destinationId(standardSync.getDestinationId()) - .operationIds(standardSync.getOperationIds()) - .name(PRESTO_TO_HUDI) - .namespaceDefinition(NamespaceDefinitionType.SOURCE) - .namespaceFormat(null) - .prefix(PRESTO_TO_HUDI_PREFIX) - .status(ConnectionStatus.ACTIVE) - .schedule(ConnectionHelpers.generateBasicConnectionSchedule()) - .syncCatalog(catalog) - .resourceRequirements(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(standardSync.getResourceRequirements().getCpuRequest()) - .cpuLimit(standardSync.getResourceRequirements().getCpuLimit()) - .memoryRequest(standardSync.getResourceRequirements().getMemoryRequest()) - .memoryLimit(standardSync.getResourceRequirements().getMemoryLimit())); - - Assert.assertThrows(IllegalArgumentException.class, () -> { - connectionsHandler.createConnection(connectionCreate); - }); - } - - @Test - void testEnumConversion() { - assertTrue(Enums.isCompatible(ConnectionStatus.class, StandardSync.Status.class)); - assertTrue(Enums.isCompatible(io.airbyte.config.SyncMode.class, SyncMode.class)); - assertTrue(Enums.isCompatible(StandardSync.Status.class, ConnectionStatus.class)); - assertTrue(Enums.isCompatible(ConnectionSchedule.TimeUnitEnum.class, Schedule.TimeUnit.class)); - assertTrue(Enums.isCompatible(io.airbyte.api.model.generated.DataType.class, DataType.class)); - assertTrue(Enums.isCompatible(DataType.class, io.airbyte.api.model.generated.DataType.class)); - assertTrue(Enums.isCompatible(NamespaceDefinitionType.class, io.airbyte.config.JobSyncConfig.NamespaceDefinitionType.class)); - } - - } - - @Nested - class StreamConfigurationDiff { - - @BeforeEach - void setUp() { - connectionsHandler = new ConnectionsHandler( - configRepository, - uuidGenerator, - workspaceHelper, - trackingClient, - eventRunner, - connectionHelper); - } - - @Test - void testNoDiff() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - - assertTrue(connectionsHandler.getConfigurationDiff(catalog1, catalog2).isEmpty()); - } - - @Test - void testNoDiffIfStreamAdded() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - - assertTrue(connectionsHandler.getConfigurationDiff(catalog1, catalog2).isEmpty()); - } - - @Test - void testCursorOrderDoesMatter() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1, "anotherCursor"), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration1WithOtherCursorOrder = getStreamConfiguration( - List.of("anotherCursor", CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1WithOtherCursorOrder), - getStreamAndConfig(STREAM2, streamConfiguration2))); - - final Set changedSd = connectionsHandler.getConfigurationDiff(catalog1, catalog2); - assertFalse(changedSd.isEmpty()); - assertEquals(1, changedSd.size()); - assertEquals(Set.of(new StreamDescriptor().name(STREAM1)), changedSd); - } - - @Test - void testPkOrderDoesntMatter() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1, PK3)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration1WithOtherPkOrder = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK3, PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2), List.of(PK3)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteStreamConfiguration streamConfiguration2WithOtherPkOrder = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK3), List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1WithOtherPkOrder), - getStreamAndConfig(STREAM2, streamConfiguration2WithOtherPkOrder))); - - final Set changedSd = connectionsHandler.getConfigurationDiff(catalog1, catalog2); - assertFalse(changedSd.isEmpty()); - assertEquals(1, changedSd.size()); - assertEquals(Set.of(new StreamDescriptor().name(STREAM1)), changedSd); - } - - @Test - void testNoDiffIfStreamRemove() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1))); - - assertTrue(connectionsHandler.getConfigurationDiff(catalog1, catalog2).isEmpty()); - } - - @Test - void testDiffDifferentCursor() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration1CursorDiff = getStreamConfiguration( - List.of(CURSOR1, "anotherCursor"), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1CursorDiff), - getStreamAndConfig(STREAM2, streamConfiguration2))); - - final Set changedSd = connectionsHandler.getConfigurationDiff(catalog1, catalog2); - assertFalse(changedSd.isEmpty()); - assertEquals(1, changedSd.size()); - assertEquals(Set.of(new StreamDescriptor().name(STREAM1)), changedSd); - } - - @Test - void testDiffIfDifferentPrimaryKey() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration1WithPkDiff = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1, PK3)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2WithPkDiff = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1), List.of(PK3)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1WithPkDiff), - getStreamAndConfig(STREAM2, streamConfiguration2WithPkDiff))); - - final Set changedSd = connectionsHandler.getConfigurationDiff(catalog1, catalog2); - assertFalse(changedSd.isEmpty()); - assertEquals(2, changedSd.size()); - Assertions.assertThat(changedSd) - .containsExactlyInAnyOrder(new StreamDescriptor().name(STREAM1), new StreamDescriptor().name(STREAM2)); - } - - @Test - void testDiffDifferentSyncMode() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration1CursorDiff = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1CursorDiff), - getStreamAndConfig(STREAM2, streamConfiguration2))); - - final Set changedSd = connectionsHandler.getConfigurationDiff(catalog1, catalog2); - assertFalse(changedSd.isEmpty()); - assertEquals(1, changedSd.size()); - assertEquals(Set.of(new StreamDescriptor().name(STREAM1)), changedSd); - } - - @Test - void testDiffDifferentDestinationSyncMode() { - final AirbyteStreamConfiguration streamConfiguration1 = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND_DEDUP); - - final AirbyteStreamConfiguration streamConfiguration1CursorDiff = getStreamConfiguration( - List.of(CURSOR1), - List.of(List.of(PK1)), - SyncMode.INCREMENTAL, - DestinationSyncMode.APPEND); - - final AirbyteStreamConfiguration streamConfiguration2 = getStreamConfiguration( - List.of(CURSOR2), - List.of(List.of(PK2)), - SyncMode.FULL_REFRESH, - DestinationSyncMode.OVERWRITE); - - final AirbyteCatalog catalog1 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1), - getStreamAndConfig(STREAM2, streamConfiguration2))); - final AirbyteCatalog catalog2 = new AirbyteCatalog() - .streams( - List.of( - getStreamAndConfig(STREAM1, streamConfiguration1CursorDiff), - getStreamAndConfig(STREAM2, streamConfiguration2))); - - final Set changedSd = connectionsHandler.getConfigurationDiff(catalog1, catalog2); - assertFalse(changedSd.isEmpty()); - assertEquals(1, changedSd.size()); - assertEquals(Set.of(new StreamDescriptor().name(STREAM1)), changedSd); - } - - private AirbyteStreamAndConfiguration getStreamAndConfig(final String name, final AirbyteStreamConfiguration config) { - return new AirbyteStreamAndConfiguration() - .config(config) - .stream(new AirbyteStream().name(name)); - } - - private AirbyteStreamConfiguration getStreamConfiguration(final List cursors, - final List> primaryKeys, - final SyncMode syncMode, - final DestinationSyncMode destinationSyncMode) { - return new AirbyteStreamConfiguration() - .cursorField(cursors) - .primaryKey(primaryKeys) - .syncMode(syncMode) - .destinationSyncMode(destinationSyncMode); - - } - - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandlerTest.java deleted file mode 100644 index 27201fb73305c..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationDefinitionsHandlerTest.java +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.CustomDestinationDefinitionCreate; -import io.airbyte.api.model.generated.DestinationDefinitionCreate; -import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.DestinationDefinitionRead; -import io.airbyte.api.model.generated.DestinationDefinitionReadList; -import io.airbyte.api.model.generated.DestinationDefinitionUpdate; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationReadList; -import io.airbyte.api.model.generated.PrivateDestinationDefinitionRead; -import io.airbyte.api.model.generated.PrivateDestinationDefinitionReadList; -import io.airbyte.api.model.generated.ReleaseStage; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.commons.server.errors.UnsupportedProtocolVersionException; -import io.airbyte.commons.server.scheduler.SynchronousJobMetadata; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorDefinitionResourceRequirements; -import io.airbyte.config.ActorType; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.NormalizationDestinationDefinitionConfig; -import io.airbyte.config.ResourceRequirements; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.time.LocalDate; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; -import java.util.function.Supplier; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -class DestinationDefinitionsHandlerTest { - - private static final String TODAY_DATE_STRING = LocalDate.now().toString(); - private static final String DEFAULT_PROTOCOL_VERSION = "0.2.0"; - - private ConfigRepository configRepository; - private StandardDestinationDefinition destinationDefinition; - private StandardDestinationDefinition destinationDefinitionWithNormalization; - - private DestinationDefinitionsHandler destinationDefinitionsHandler; - private Supplier uuidSupplier; - private SynchronousSchedulerClient schedulerSynchronousClient; - private AirbyteGithubStore githubStore; - private DestinationHandler destinationHandler; - private UUID workspaceId; - private AirbyteProtocolVersionRange protocolVersionRange; - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() { - configRepository = mock(ConfigRepository.class); - uuidSupplier = mock(Supplier.class); - destinationDefinition = generateDestinationDefinition(); - destinationDefinitionWithNormalization = generateDestinationDefinitionWithNormalization(); - schedulerSynchronousClient = spy(SynchronousSchedulerClient.class); - githubStore = mock(AirbyteGithubStore.class); - destinationHandler = mock(DestinationHandler.class); - workspaceId = UUID.randomUUID(); - protocolVersionRange = new AirbyteProtocolVersionRange(new Version("0.0.0"), new Version("0.3.0")); - - destinationDefinitionsHandler = new DestinationDefinitionsHandler( - configRepository, - uuidSupplier, - schedulerSynchronousClient, - githubStore, - destinationHandler, - protocolVersionRange); - } - - private StandardDestinationDefinition generateDestinationDefinition() { - final ConnectorSpecification spec = new ConnectorSpecification() - .withConnectionSpecification(Jsons.jsonNode(ImmutableMap.of("foo", "bar"))); - - return new StandardDestinationDefinition() - .withDestinationDefinitionId(UUID.randomUUID()) - .withName("presto") - .withDockerImageTag("12.3") - .withDockerRepository("repo") - .withDocumentationUrl("https://hulu.com") - .withIcon("http.svg") - .withSpec(spec) - .withProtocolVersion("0.2.2") - .withTombstone(false) - .withReleaseStage(StandardDestinationDefinition.ReleaseStage.ALPHA) - .withReleaseDate(TODAY_DATE_STRING) - .withResourceRequirements(new ActorDefinitionResourceRequirements().withDefault(new ResourceRequirements().withCpuRequest("2"))); - } - - private StandardDestinationDefinition generateDestinationDefinitionWithNormalization() { - final StandardDestinationDefinition definition = generateDestinationDefinition(); - return definition - .withSupportsDbt(true) - .withNormalizationConfig(new NormalizationDestinationDefinitionConfig() - .withNormalizationRepository("repository") - .withNormalizationTag("dev") - .withNormalizationIntegrationType("integration-type")); - } - - @Test - @DisplayName("listDestinationDefinition should return the right list") - void testListDestinations() throws JsonValidationException, IOException, URISyntaxException { - - when(configRepository.listStandardDestinationDefinitions(false)) - .thenReturn(Lists.newArrayList(destinationDefinition, destinationDefinitionWithNormalization)); - - final DestinationDefinitionRead expectedDestinationDefinitionRead1 = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .name(destinationDefinition.getName()) - .dockerRepository(destinationDefinition.getDockerRepository()) - .dockerImageTag(destinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinition.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinition.getIcon())) - .protocolVersion(destinationDefinition.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinition.getReleaseDate())) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionRead expectedDestinationDefinitionRead2 = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinitionWithNormalization.getDestinationDefinitionId()) - .name(destinationDefinitionWithNormalization.getName()) - .dockerRepository(destinationDefinitionWithNormalization.getDockerRepository()) - .dockerImageTag(destinationDefinitionWithNormalization.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinitionWithNormalization.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinitionWithNormalization.getIcon())) - .protocolVersion(destinationDefinitionWithNormalization.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinitionWithNormalization.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinitionWithNormalization.getReleaseDate())) - .supportsDbt(destinationDefinitionWithNormalization.getSupportsDbt()) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(true) - .normalizationRepository(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationRepository()) - .normalizationTag(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationTag()) - .normalizationIntegrationType(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationIntegrationType())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinitionWithNormalization.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionReadList actualDestinationDefinitionReadList = destinationDefinitionsHandler.listDestinationDefinitions(); - - assertEquals( - Lists.newArrayList(expectedDestinationDefinitionRead1, expectedDestinationDefinitionRead2), - actualDestinationDefinitionReadList.getDestinationDefinitions()); - } - - @Test - @DisplayName("listDestinationDefinitionsForWorkspace should return the right list") - void testListDestinationDefinitionsForWorkspace() throws IOException, URISyntaxException { - - when(configRepository.listPublicDestinationDefinitions(false)).thenReturn(Lists.newArrayList(destinationDefinition)); - when(configRepository.listGrantedDestinationDefinitions(workspaceId, false)) - .thenReturn(Lists.newArrayList(destinationDefinitionWithNormalization)); - - final DestinationDefinitionRead expectedDestinationDefinitionRead1 = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .name(destinationDefinition.getName()) - .dockerRepository(destinationDefinition.getDockerRepository()) - .dockerImageTag(destinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinition.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinition.getIcon())) - .protocolVersion(destinationDefinition.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinition.getReleaseDate())) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionRead expectedDestinationDefinitionRead2 = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinitionWithNormalization.getDestinationDefinitionId()) - .name(destinationDefinitionWithNormalization.getName()) - .dockerRepository(destinationDefinitionWithNormalization.getDockerRepository()) - .dockerImageTag(destinationDefinitionWithNormalization.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinitionWithNormalization.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinitionWithNormalization.getIcon())) - .protocolVersion(destinationDefinitionWithNormalization.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinitionWithNormalization.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinitionWithNormalization.getReleaseDate())) - .supportsDbt(destinationDefinitionWithNormalization.getSupportsDbt()) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(true) - .normalizationRepository(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationRepository()) - .normalizationTag(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationTag()) - .normalizationIntegrationType(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationIntegrationType())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinitionWithNormalization.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionReadList actualDestinationDefinitionReadList = destinationDefinitionsHandler - .listDestinationDefinitionsForWorkspace(new WorkspaceIdRequestBody().workspaceId(workspaceId)); - - assertEquals( - Lists.newArrayList(expectedDestinationDefinitionRead1, expectedDestinationDefinitionRead2), - actualDestinationDefinitionReadList.getDestinationDefinitions()); - } - - @Test - @DisplayName("listPrivateDestinationDefinitions should return the right list") - void testListPrivateDestinationDefinitions() throws IOException, URISyntaxException { - - when(configRepository.listGrantableDestinationDefinitions(workspaceId, false)).thenReturn( - Lists.newArrayList( - Map.entry(destinationDefinition, false), - Map.entry(destinationDefinitionWithNormalization, true))); - - final DestinationDefinitionRead expectedDestinationDefinitionRead1 = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .name(destinationDefinition.getName()) - .dockerRepository(destinationDefinition.getDockerRepository()) - .dockerImageTag(destinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinition.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinition.getIcon())) - .protocolVersion(destinationDefinition.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinition.getReleaseDate())) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionRead expectedDestinationDefinitionRead2 = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinitionWithNormalization.getDestinationDefinitionId()) - .name(destinationDefinitionWithNormalization.getName()) - .dockerRepository(destinationDefinitionWithNormalization.getDockerRepository()) - .dockerImageTag(destinationDefinitionWithNormalization.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinitionWithNormalization.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinitionWithNormalization.getIcon())) - .protocolVersion(destinationDefinitionWithNormalization.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinitionWithNormalization.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinitionWithNormalization.getReleaseDate())) - .supportsDbt(destinationDefinitionWithNormalization.getSupportsDbt()) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(true) - .normalizationRepository(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationRepository()) - .normalizationTag(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationTag()) - .normalizationIntegrationType(destinationDefinitionWithNormalization.getNormalizationConfig().getNormalizationIntegrationType())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinitionWithNormalization.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final PrivateDestinationDefinitionRead expectedDestinationDefinitionOptInRead1 = - new PrivateDestinationDefinitionRead().destinationDefinition(expectedDestinationDefinitionRead1).granted(false); - - final PrivateDestinationDefinitionRead expectedDestinationDefinitionOptInRead2 = - new PrivateDestinationDefinitionRead().destinationDefinition(expectedDestinationDefinitionRead2).granted(true); - - final PrivateDestinationDefinitionReadList actualDestinationDefinitionOptInReadList = - destinationDefinitionsHandler.listPrivateDestinationDefinitions( - new WorkspaceIdRequestBody().workspaceId(workspaceId)); - - assertEquals( - Lists.newArrayList(expectedDestinationDefinitionOptInRead1, expectedDestinationDefinitionOptInRead2), - actualDestinationDefinitionOptInReadList.getDestinationDefinitions()); - } - - @Test - @DisplayName("getDestinationDefinition should return the right destination") - void testGetDestination() throws JsonValidationException, ConfigNotFoundException, IOException, URISyntaxException { - when(configRepository.getStandardDestinationDefinition(destinationDefinition.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - - final DestinationDefinitionRead expectedDestinationDefinitionRead = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .name(destinationDefinition.getName()) - .dockerRepository(destinationDefinition.getDockerRepository()) - .dockerImageTag(destinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinition.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinition.getIcon())) - .protocolVersion(destinationDefinition.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinition.getReleaseDate())) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody = new DestinationDefinitionIdRequestBody() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()); - - final DestinationDefinitionRead actualDestinationDefinitionRead = - destinationDefinitionsHandler.getDestinationDefinition(destinationDefinitionIdRequestBody); - - assertEquals(expectedDestinationDefinitionRead, actualDestinationDefinitionRead); - } - - @Test - @DisplayName("getDestinationDefinitionForWorkspace should throw an exception for a missing grant") - void testGetDefinitionWithoutGrantForWorkspace() throws IOException { - when(configRepository.workspaceCanUseDefinition(destinationDefinition.getDestinationDefinitionId(), workspaceId)) - .thenReturn(false); - - final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId = new DestinationDefinitionIdWithWorkspaceId() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .workspaceId(workspaceId); - - assertThrows(IdNotFoundKnownException.class, - () -> destinationDefinitionsHandler.getDestinationDefinitionForWorkspace(destinationDefinitionIdWithWorkspaceId)); - } - - @Test - @DisplayName("getDestinationDefinitionForWorkspace should return the destination if the grant exists") - void testGetDefinitionWithGrantForWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException, URISyntaxException { - when(configRepository.workspaceCanUseDefinition(destinationDefinition.getDestinationDefinitionId(), workspaceId)) - .thenReturn(true); - when(configRepository.getStandardDestinationDefinition(destinationDefinition.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - - final DestinationDefinitionRead expectedDestinationDefinitionRead = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .name(destinationDefinition.getName()) - .dockerRepository(destinationDefinition.getDockerRepository()) - .dockerImageTag(destinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinition.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinition.getIcon())) - .protocolVersion(destinationDefinition.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinition.getReleaseDate())) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId = new DestinationDefinitionIdWithWorkspaceId() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .workspaceId(workspaceId); - - final DestinationDefinitionRead actualDestinationDefinitionRead = destinationDefinitionsHandler - .getDestinationDefinitionForWorkspace(destinationDefinitionIdWithWorkspaceId); - - assertEquals(expectedDestinationDefinitionRead, actualDestinationDefinitionRead); - } - - @Test - @DisplayName("createDestinationDefinition should not create a destinationDefinition with unsupported protocol version") - void testCreateDestinationDefinitionShouldCheckProtocolVersion() throws URISyntaxException, IOException, JsonValidationException { - final String invalidProtocolVersion = "121.5.6"; - final StandardDestinationDefinition destination = generateDestinationDefinition(); - destination.getSpec().setProtocolVersion(invalidProtocolVersion); - final String imageName = destination.getDockerRepository() + ":" + destination.getDockerImageTag(); - - when(uuidSupplier.get()).thenReturn(destination.getDestinationDefinitionId()); - when(schedulerSynchronousClient.createGetSpecJob(imageName, true)).thenReturn(new SynchronousResponse<>( - destination.getSpec(), - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final DestinationDefinitionCreate create = new DestinationDefinitionCreate() - .name(destination.getName()) - .dockerRepository(destination.getDockerRepository()) - .dockerImageTag(destination.getDockerImageTag()) - .documentationUrl(new URI(destination.getDocumentationUrl())) - .icon(destination.getIcon()) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destination.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final CustomDestinationDefinitionCreate customCreate = new CustomDestinationDefinitionCreate() - .destinationDefinition(create) - .workspaceId(workspaceId); - - assertThrows(UnsupportedProtocolVersionException.class, () -> destinationDefinitionsHandler.createCustomDestinationDefinition(customCreate)); - - verify(schedulerSynchronousClient).createGetSpecJob(imageName, true); - verify(configRepository, never()).writeStandardDestinationDefinition(destination - .withProtocolVersion(DEFAULT_PROTOCOL_VERSION) - .withReleaseDate(null) - .withReleaseStage(StandardDestinationDefinition.ReleaseStage.CUSTOM)); - } - - @Test - @DisplayName("createCustomDestinationDefinition should correctly create a destinationDefinition") - void testCreateCustomDestinationDefinition() throws URISyntaxException, IOException, JsonValidationException { - final StandardDestinationDefinition destination = generateDestinationDefinition(); - final String imageName = destination.getDockerRepository() + ":" + destination.getDockerImageTag(); - - when(uuidSupplier.get()).thenReturn(destination.getDestinationDefinitionId()); - when(schedulerSynchronousClient.createGetSpecJob(imageName, true)).thenReturn(new SynchronousResponse<>( - destination.getSpec(), - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final DestinationDefinitionCreate create = new DestinationDefinitionCreate() - .name(destination.getName()) - .dockerRepository(destination.getDockerRepository()) - .dockerImageTag(destination.getDockerImageTag()) - .documentationUrl(new URI(destination.getDocumentationUrl())) - .icon(destination.getIcon()) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destination.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final CustomDestinationDefinitionCreate customCreate = new CustomDestinationDefinitionCreate() - .destinationDefinition(create) - .workspaceId(workspaceId); - - final DestinationDefinitionRead expectedRead = new DestinationDefinitionRead() - .name(destination.getName()) - .dockerRepository(destination.getDockerRepository()) - .dockerImageTag(destination.getDockerImageTag()) - .documentationUrl(new URI(destination.getDocumentationUrl())) - .destinationDefinitionId(destination.getDestinationDefinitionId()) - .icon(DestinationDefinitionsHandler.loadIcon(destination.getIcon())) - .protocolVersion(DEFAULT_PROTOCOL_VERSION) - .releaseStage(ReleaseStage.CUSTOM) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destination.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final DestinationDefinitionRead actualRead = destinationDefinitionsHandler.createCustomDestinationDefinition(customCreate); - - assertEquals(expectedRead, actualRead); - verify(schedulerSynchronousClient).createGetSpecJob(imageName, true); - verify(configRepository).writeCustomDestinationDefinition( - destination - .withProtocolVersion(DEFAULT_PROTOCOL_VERSION) - .withReleaseDate(null) - .withReleaseStage(StandardDestinationDefinition.ReleaseStage.CUSTOM) - .withCustom(true), - workspaceId); - } - - @Test - @DisplayName("createCustomDestinationDefinition should not create a destinationDefinition with unsupported protocol range") - void testCreateCustomDestinationDefinitionWithInvalidProtocol() throws URISyntaxException, IOException, JsonValidationException { - final String invalidProtocol = "122.1.22"; - final StandardDestinationDefinition destination = generateDestinationDefinition(); - destination.getSpec().setProtocolVersion(invalidProtocol); - final String imageName = destination.getDockerRepository() + ":" + destination.getDockerImageTag(); - - when(uuidSupplier.get()).thenReturn(destination.getDestinationDefinitionId()); - when(schedulerSynchronousClient.createGetSpecJob(imageName, true)).thenReturn(new SynchronousResponse<>( - destination.getSpec(), - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final DestinationDefinitionCreate create = new DestinationDefinitionCreate() - .name(destination.getName()) - .dockerRepository(destination.getDockerRepository()) - .dockerImageTag(destination.getDockerImageTag()) - .documentationUrl(new URI(destination.getDocumentationUrl())) - .icon(destination.getIcon()) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destination.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final CustomDestinationDefinitionCreate customCreate = new CustomDestinationDefinitionCreate() - .destinationDefinition(create) - .workspaceId(workspaceId); - - assertThrows(UnsupportedProtocolVersionException.class, () -> destinationDefinitionsHandler.createCustomDestinationDefinition(customCreate)); - - verify(schedulerSynchronousClient).createGetSpecJob(imageName, true); - verify(configRepository, never()).writeCustomDestinationDefinition( - destination - .withProtocolVersion(invalidProtocol) - .withReleaseDate(null) - .withReleaseStage(StandardDestinationDefinition.ReleaseStage.CUSTOM) - .withCustom(true), - workspaceId); - } - - @Test - @DisplayName("updateDestinationDefinition should correctly update a destinationDefinition") - void testUpdateDestination() throws ConfigNotFoundException, IOException, JsonValidationException { - when(configRepository.getStandardDestinationDefinition(destinationDefinition.getDestinationDefinitionId())).thenReturn(destinationDefinition); - final DestinationDefinitionRead currentDestination = destinationDefinitionsHandler - .getDestinationDefinition( - new DestinationDefinitionIdRequestBody().destinationDefinitionId(destinationDefinition.getDestinationDefinitionId())); - final String currentTag = currentDestination.getDockerImageTag(); - final String newDockerImageTag = "averydifferenttag"; - final String newProtocolVersion = "0.2.4"; - assertNotEquals(newDockerImageTag, currentTag); - assertNotEquals(newProtocolVersion, currentDestination.getProtocolVersion()); - - final String newImageName = destinationDefinition.getDockerRepository() + ":" + newDockerImageTag; - final ConnectorSpecification newSpec = new ConnectorSpecification() - .withConnectionSpecification(Jsons.jsonNode(ImmutableMap.of("foo2", "bar2"))) - .withProtocolVersion(newProtocolVersion); - when(schedulerSynchronousClient.createGetSpecJob(newImageName, false)).thenReturn(new SynchronousResponse<>( - newSpec, - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final StandardDestinationDefinition updatedDestination = - Jsons.clone(destinationDefinition).withDockerImageTag(newDockerImageTag).withSpec(newSpec).withProtocolVersion(newProtocolVersion); - - final DestinationDefinitionRead destinationRead = destinationDefinitionsHandler.updateDestinationDefinition( - new DestinationDefinitionUpdate().destinationDefinitionId(this.destinationDefinition.getDestinationDefinitionId()) - .dockerImageTag(newDockerImageTag)); - - assertEquals(newDockerImageTag, destinationRead.getDockerImageTag()); - verify(schedulerSynchronousClient).createGetSpecJob(newImageName, false); - verify(configRepository).writeStandardDestinationDefinition(updatedDestination); - - verify(configRepository).clearUnsupportedProtocolVersionFlag(updatedDestination.getDestinationDefinitionId(), ActorType.DESTINATION, - protocolVersionRange); - } - - @Test - @DisplayName("updateDestinationDefinition should not update a destinationDefinition if protocol version is out of range") - void testOutOfProtocolRangeUpdateDestination() throws ConfigNotFoundException, IOException, JsonValidationException { - when(configRepository.getStandardDestinationDefinition(destinationDefinition.getDestinationDefinitionId())).thenReturn(destinationDefinition); - final DestinationDefinitionRead currentDestination = destinationDefinitionsHandler - .getDestinationDefinition( - new DestinationDefinitionIdRequestBody().destinationDefinitionId(destinationDefinition.getDestinationDefinitionId())); - final String currentTag = currentDestination.getDockerImageTag(); - final String newDockerImageTag = "averydifferenttagforprotocolversion"; - final String newProtocolVersion = "120.2.4"; - assertNotEquals(newDockerImageTag, currentTag); - assertNotEquals(newProtocolVersion, currentDestination.getProtocolVersion()); - - final String newImageName = destinationDefinition.getDockerRepository() + ":" + newDockerImageTag; - final ConnectorSpecification newSpec = new ConnectorSpecification() - .withConnectionSpecification(Jsons.jsonNode(ImmutableMap.of("foo2", "bar2"))) - .withProtocolVersion(newProtocolVersion); - when(schedulerSynchronousClient.createGetSpecJob(newImageName, false)).thenReturn(new SynchronousResponse<>( - newSpec, - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final StandardDestinationDefinition updatedDestination = - Jsons.clone(destinationDefinition).withDockerImageTag(newDockerImageTag).withSpec(newSpec).withProtocolVersion(newProtocolVersion); - - assertThrows(UnsupportedProtocolVersionException.class, () -> destinationDefinitionsHandler.updateDestinationDefinition( - new DestinationDefinitionUpdate().destinationDefinitionId(this.destinationDefinition.getDestinationDefinitionId()) - .dockerImageTag(newDockerImageTag))); - - verify(schedulerSynchronousClient).createGetSpecJob(newImageName, false); - verify(configRepository, never()).writeStandardDestinationDefinition(updatedDestination); - } - - @Test - @DisplayName("deleteDestinationDefinition should correctly delete a sourceDefinition") - void testDeleteDestinationDefinition() throws ConfigNotFoundException, IOException, JsonValidationException { - final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody = - new DestinationDefinitionIdRequestBody().destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()); - final StandardDestinationDefinition updatedDestinationDefinition = Jsons.clone(this.destinationDefinition).withTombstone(true); - final DestinationRead destination = new DestinationRead(); - - when(configRepository.getStandardDestinationDefinition(destinationDefinition.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - when(destinationHandler.listDestinationsForDestinationDefinition(destinationDefinitionIdRequestBody)) - .thenReturn(new DestinationReadList().destinations(Collections.singletonList(destination))); - - assertFalse(destinationDefinition.getTombstone()); - - destinationDefinitionsHandler.deleteDestinationDefinition(destinationDefinitionIdRequestBody); - - verify(destinationHandler).deleteDestination(destination); - verify(configRepository).writeStandardDestinationDefinition(updatedDestinationDefinition); - } - - @Test - @DisplayName("grantDestinationDefinitionToWorkspace should correctly create a workspace grant") - void testGrantDestinationDefinitionToWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException, URISyntaxException { - when(configRepository.getStandardDestinationDefinition(destinationDefinition.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - - final DestinationDefinitionRead expectedDestinationDefinitionRead = new DestinationDefinitionRead() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .name(destinationDefinition.getName()) - .dockerRepository(destinationDefinition.getDockerRepository()) - .dockerImageTag(destinationDefinition.getDockerImageTag()) - .documentationUrl(new URI(destinationDefinition.getDocumentationUrl())) - .icon(DestinationDefinitionsHandler.loadIcon(destinationDefinition.getIcon())) - .protocolVersion(destinationDefinition.getProtocolVersion()) - .releaseStage(ReleaseStage.fromValue(destinationDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(destinationDefinition.getReleaseDate())) - .supportsDbt(false) - .normalizationConfig(new io.airbyte.api.model.generated.NormalizationDestinationDefinitionConfig().supported(false)) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(destinationDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final PrivateDestinationDefinitionRead expectedPrivateDestinationDefinitionRead = - new PrivateDestinationDefinitionRead().destinationDefinition(expectedDestinationDefinitionRead).granted(true); - - final PrivateDestinationDefinitionRead actualPrivateDestinationDefinitionRead = - destinationDefinitionsHandler.grantDestinationDefinitionToWorkspace( - new DestinationDefinitionIdWithWorkspaceId() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .workspaceId(workspaceId)); - - assertEquals(expectedPrivateDestinationDefinitionRead, actualPrivateDestinationDefinitionRead); - verify(configRepository).writeActorDefinitionWorkspaceGrant( - destinationDefinition.getDestinationDefinitionId(), - workspaceId); - } - - @Test - @DisplayName("revokeDestinationDefinitionFromWorkspace should correctly delete a workspace grant") - void testRevokeDestinationDefinitionFromWorkspace() throws IOException { - destinationDefinitionsHandler.revokeDestinationDefinitionFromWorkspace(new DestinationDefinitionIdWithWorkspaceId() - .destinationDefinitionId(destinationDefinition.getDestinationDefinitionId()) - .workspaceId(workspaceId)); - verify(configRepository).deleteActorDefinitionWorkspaceGrant( - destinationDefinition.getDestinationDefinitionId(), - workspaceId); - } - - @Nested - @DisplayName("listLatest") - class listLatest { - - @Test - @DisplayName("should return the latest list") - void testCorrect() throws InterruptedException { - final StandardDestinationDefinition destinationDefinition = generateDestinationDefinition(); - when(githubStore.getLatestDestinations()).thenReturn(Collections.singletonList(destinationDefinition)); - - final var destinationDefinitionReadList = destinationDefinitionsHandler.listLatestDestinationDefinitions().getDestinationDefinitions(); - assertEquals(1, destinationDefinitionReadList.size()); - - final var destinationDefinitionRead = destinationDefinitionReadList.get(0); - assertEquals(DestinationDefinitionsHandler.buildDestinationDefinitionRead(destinationDefinition), destinationDefinitionRead); - } - - @Test - @DisplayName("returns empty collection if cannot find latest definitions") - void testHttpTimeout() { - assertEquals(0, destinationDefinitionsHandler.listLatestDestinationDefinitions().getDestinationDefinitions().size()); - } - - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationHandlerTest.java deleted file mode 100644 index 390d7a8b7e1a5..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/DestinationHandlerTest.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.DestinationCloneConfiguration; -import io.airbyte.api.model.generated.DestinationCloneRequestBody; -import io.airbyte.api.model.generated.DestinationCreate; -import io.airbyte.api.model.generated.DestinationDefinitionSpecificationRead; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationReadList; -import io.airbyte.api.model.generated.DestinationSearch; -import io.airbyte.api.model.generated.DestinationUpdate; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.ConfigurationUpdate; -import io.airbyte.commons.server.helpers.ConnectorSpecificationHelpers; -import io.airbyte.commons.server.helpers.DestinationHelpers; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.util.UUID; -import java.util.function.Supplier; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class DestinationHandlerTest { - - private ConfigRepository configRepository; - private SecretsRepositoryReader secretsRepositoryReader; - private SecretsRepositoryWriter secretsRepositoryWriter; - private StandardDestinationDefinition standardDestinationDefinition; - private DestinationDefinitionSpecificationRead destinationDefinitionSpecificationRead; - private DestinationConnection destinationConnection; - private DestinationHandler destinationHandler; - private ConnectionsHandler connectionsHandler; - private ConfigurationUpdate configurationUpdate; - private JsonSchemaValidator validator; - private Supplier uuidGenerator; - private JsonSecretsProcessor secretsProcessor; - private ConnectorSpecification connectorSpecification; - private OAuthConfigSupplier oAuthConfigSupplier; - - // needs to match name of file in src/test/resources/icons - private static final String ICON = "test-destination.svg"; - private static final String LOADED_ICON = DestinationDefinitionsHandler.loadIcon(ICON); - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() throws IOException { - configRepository = mock(ConfigRepository.class); - secretsRepositoryReader = mock(SecretsRepositoryReader.class); - secretsRepositoryWriter = mock(SecretsRepositoryWriter.class); - validator = mock(JsonSchemaValidator.class); - uuidGenerator = mock(Supplier.class); - connectionsHandler = mock(ConnectionsHandler.class); - configurationUpdate = mock(ConfigurationUpdate.class); - secretsProcessor = mock(JsonSecretsProcessor.class); - oAuthConfigSupplier = mock(OAuthConfigSupplier.class); - - connectorSpecification = ConnectorSpecificationHelpers.generateConnectorSpecification(); - - standardDestinationDefinition = new StandardDestinationDefinition() - .withDestinationDefinitionId(UUID.randomUUID()) - .withName("db2") - .withDockerRepository("thebestrepo") - .withDockerImageTag("thelatesttag") - .withDocumentationUrl("https://wikipedia.org") - .withSpec(connectorSpecification) - .withIcon(ICON); - - destinationDefinitionSpecificationRead = new DestinationDefinitionSpecificationRead() - .connectionSpecification(connectorSpecification.getConnectionSpecification()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .documentationUrl(connectorSpecification.getDocumentationUrl().toString()); - - destinationConnection = DestinationHelpers.generateDestination(standardDestinationDefinition.getDestinationDefinitionId()); - - destinationHandler = - new DestinationHandler(configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - validator, - connectionsHandler, - uuidGenerator, - secretsProcessor, - configurationUpdate, - oAuthConfigSupplier); - } - - @Test - void testCreateDestination() throws JsonValidationException, ConfigNotFoundException, IOException { - when(uuidGenerator.get()) - .thenReturn(destinationConnection.getDestinationId()); - when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())) - .thenReturn(destinationConnection); - when(configRepository.getStandardDestinationDefinition(standardDestinationDefinition.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - when(oAuthConfigSupplier.maskDestinationOAuthParameters(destinationDefinitionSpecificationRead.getDestinationDefinitionId(), - destinationConnection.getWorkspaceId(), - destinationConnection.getConfiguration())).thenReturn(destinationConnection.getConfiguration()); - when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(), - destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(destinationConnection.getConfiguration()); - - final DestinationCreate destinationCreate = new DestinationCreate() - .name(destinationConnection.getName()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .connectionConfiguration(DestinationHelpers.getTestDestinationJson()); - - final DestinationRead actualDestinationRead = - destinationHandler.createDestination(destinationCreate); - - final DestinationRead expectedDestinationRead = new DestinationRead() - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(DestinationHelpers.getTestDestinationJson()) - .destinationName(standardDestinationDefinition.getName()) - .icon(LOADED_ICON); - - assertEquals(expectedDestinationRead, actualDestinationRead); - - verify(validator).ensure(destinationDefinitionSpecificationRead.getConnectionSpecification(), destinationConnection.getConfiguration()); - verify(secretsRepositoryWriter).writeDestinationConnection(destinationConnection, connectorSpecification); - verify(oAuthConfigSupplier).maskDestinationOAuthParameters(destinationDefinitionSpecificationRead.getDestinationDefinitionId(), - destinationConnection.getWorkspaceId(), destinationConnection.getConfiguration()); - verify(secretsProcessor) - .prepareSecretsForOutput(destinationConnection.getConfiguration(), destinationDefinitionSpecificationRead.getConnectionSpecification()); - } - - @Test - void testUpdateDestination() throws JsonValidationException, ConfigNotFoundException, IOException { - final String updatedDestName = "my updated dest name"; - final JsonNode newConfiguration = destinationConnection.getConfiguration(); - ((ObjectNode) newConfiguration).put("apiKey", "987-xyz"); - - final DestinationConnection expectedDestinationConnection = Jsons.clone(destinationConnection) - .withName(updatedDestName) - .withConfiguration(newConfiguration) - .withTombstone(false); - - final DestinationUpdate destinationUpdate = new DestinationUpdate() - .name(updatedDestName) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(newConfiguration); - - when(secretsProcessor - .copySecrets(destinationConnection.getConfiguration(), newConfiguration, destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(newConfiguration); - when(secretsProcessor.prepareSecretsForOutput(newConfiguration, destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(newConfiguration); - when(oAuthConfigSupplier.maskDestinationOAuthParameters(destinationDefinitionSpecificationRead.getDestinationDefinitionId(), - destinationConnection.getWorkspaceId(), - newConfiguration)).thenReturn(newConfiguration); - when(configRepository.getStandardDestinationDefinition(standardDestinationDefinition.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - when(configRepository.getDestinationDefinitionFromDestination(destinationConnection.getDestinationId())) - .thenReturn(standardDestinationDefinition); - when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())) - .thenReturn(expectedDestinationConnection); - when(configurationUpdate.destination(destinationConnection.getDestinationId(), updatedDestName, newConfiguration)) - .thenReturn(expectedDestinationConnection); - - final DestinationRead actualDestinationRead = destinationHandler.updateDestination(destinationUpdate); - - final DestinationRead expectedDestinationRead = DestinationHelpers - .getDestinationRead(expectedDestinationConnection, standardDestinationDefinition).connectionConfiguration(newConfiguration); - - assertEquals(expectedDestinationRead, actualDestinationRead); - - verify(secretsProcessor).prepareSecretsForOutput(newConfiguration, destinationDefinitionSpecificationRead.getConnectionSpecification()); - verify(secretsRepositoryWriter).writeDestinationConnection(expectedDestinationConnection, connectorSpecification); - verify(oAuthConfigSupplier).maskDestinationOAuthParameters(destinationDefinitionSpecificationRead.getDestinationDefinitionId(), - destinationConnection.getWorkspaceId(), newConfiguration); - verify(validator).ensure(destinationDefinitionSpecificationRead.getConnectionSpecification(), newConfiguration); - } - - @Test - void testGetDestination() throws JsonValidationException, ConfigNotFoundException, IOException { - final DestinationRead expectedDestinationRead = new DestinationRead() - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()) - .icon(LOADED_ICON); - final DestinationIdRequestBody destinationIdRequestBody = - new DestinationIdRequestBody().destinationId(expectedDestinationRead.getDestinationId()); - - when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(), - destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(destinationConnection.getConfiguration()); - when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())).thenReturn(destinationConnection); - when(configRepository.getStandardDestinationDefinition(standardDestinationDefinition.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - - final DestinationRead actualDestinationRead = destinationHandler.getDestination(destinationIdRequestBody); - - assertEquals(expectedDestinationRead, actualDestinationRead); - - // make sure the icon was loaded into actual svg content - assertTrue(expectedDestinationRead.getIcon().startsWith("")); - - verify(secretsProcessor) - .prepareSecretsForOutput(destinationConnection.getConfiguration(), destinationDefinitionSpecificationRead.getConnectionSpecification()); - } - - @Test - void testListDestinationForWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - final DestinationRead expectedDestinationRead = new DestinationRead() - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()) - .icon(LOADED_ICON); - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(destinationConnection.getWorkspaceId()); - - when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())).thenReturn(destinationConnection); - when(configRepository.listWorkspaceDestinationConnection(destinationConnection.getWorkspaceId())) - .thenReturn(Lists.newArrayList(destinationConnection)); - when(configRepository.getStandardDestinationDefinition(standardDestinationDefinition.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(), - destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(destinationConnection.getConfiguration()); - - final DestinationReadList actualDestinationRead = destinationHandler.listDestinationsForWorkspace(workspaceIdRequestBody); - - assertEquals(expectedDestinationRead, actualDestinationRead.getDestinations().get(0)); - verify(secretsProcessor) - .prepareSecretsForOutput(destinationConnection.getConfiguration(), destinationDefinitionSpecificationRead.getConnectionSpecification()); - } - - @Test - void testSearchDestinations() throws JsonValidationException, ConfigNotFoundException, IOException { - final DestinationRead expectedDestinationRead = new DestinationRead() - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()) - .icon(LOADED_ICON); - - when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())).thenReturn(destinationConnection); - when(configRepository.listDestinationConnection()).thenReturn(Lists.newArrayList(destinationConnection)); - when(configRepository.getStandardDestinationDefinition(standardDestinationDefinition.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(), - destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(destinationConnection.getConfiguration()); - - when(connectionsHandler.matchSearch(new DestinationSearch(), expectedDestinationRead)).thenReturn(true); - DestinationReadList actualDestinationRead = destinationHandler.searchDestinations(new DestinationSearch()); - assertEquals(1, actualDestinationRead.getDestinations().size()); - assertEquals(expectedDestinationRead, actualDestinationRead.getDestinations().get(0)); - verify(secretsProcessor) - .prepareSecretsForOutput(destinationConnection.getConfiguration(), destinationDefinitionSpecificationRead.getConnectionSpecification()); - - when(connectionsHandler.matchSearch(new DestinationSearch(), expectedDestinationRead)).thenReturn(false); - actualDestinationRead = destinationHandler.searchDestinations(new DestinationSearch()); - assertEquals(0, actualDestinationRead.getDestinations().size()); - } - - @Test - void testCloneDestinationWithConfiguration() throws JsonValidationException, ConfigNotFoundException, IOException { - final DestinationConnection clonedConnection = DestinationHelpers.generateDestination(standardDestinationDefinition.getDestinationDefinitionId()); - final DestinationRead expectedDestinationRead = new DestinationRead() - .name(clonedConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(clonedConnection.getWorkspaceId()) - .destinationId(clonedConnection.getDestinationId()) - .connectionConfiguration(clonedConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()) - .icon(LOADED_ICON); - final DestinationRead destinationRead = new DestinationRead() - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); - - final DestinationCloneConfiguration destinationCloneConfiguration = new DestinationCloneConfiguration().name("Copy Name"); - final DestinationCloneRequestBody destinationCloneRequestBody = new DestinationCloneRequestBody() - .destinationCloneId(destinationRead.getDestinationId()).destinationConfiguration(destinationCloneConfiguration); - - when(uuidGenerator.get()).thenReturn(clonedConnection.getDestinationId()); - when(secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationConnection.getDestinationId())).thenReturn(destinationConnection); - when(configRepository.getDestinationConnection(clonedConnection.getDestinationId())).thenReturn(clonedConnection); - - when(configRepository.getStandardDestinationDefinition(destinationDefinitionSpecificationRead.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - when(configRepository.getDestinationDefinitionFromDestination(destinationConnection.getDestinationId())) - .thenReturn(standardDestinationDefinition); - when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(), - destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(destinationConnection.getConfiguration()); - - final DestinationRead actualDestinationRead = destinationHandler.cloneDestination(destinationCloneRequestBody); - - assertEquals(expectedDestinationRead, actualDestinationRead); - } - - @Test - void testCloneDestinationWithoutConfiguration() throws JsonValidationException, ConfigNotFoundException, IOException { - final DestinationConnection clonedConnection = DestinationHelpers.generateDestination(standardDestinationDefinition.getDestinationDefinitionId()); - final DestinationRead expectedDestinationRead = new DestinationRead() - .name(clonedConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(clonedConnection.getWorkspaceId()) - .destinationId(clonedConnection.getDestinationId()) - .connectionConfiguration(clonedConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()) - .icon(LOADED_ICON); - final DestinationRead destinationRead = new DestinationRead() - .name(destinationConnection.getName()) - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destinationConnection.getWorkspaceId()) - .destinationId(destinationConnection.getDestinationId()) - .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); - - final DestinationCloneRequestBody destinationCloneRequestBody = - new DestinationCloneRequestBody().destinationCloneId(destinationRead.getDestinationId()); - - when(uuidGenerator.get()).thenReturn(clonedConnection.getDestinationId()); - when(secretsRepositoryReader.getDestinationConnectionWithSecrets(destinationConnection.getDestinationId())).thenReturn(destinationConnection); - when(configRepository.getDestinationConnection(clonedConnection.getDestinationId())).thenReturn(clonedConnection); - - when(configRepository.getStandardDestinationDefinition(destinationDefinitionSpecificationRead.getDestinationDefinitionId())) - .thenReturn(standardDestinationDefinition); - when(configRepository.getDestinationDefinitionFromDestination(destinationConnection.getDestinationId())) - .thenReturn(standardDestinationDefinition); - when(secretsProcessor.prepareSecretsForOutput(destinationConnection.getConfiguration(), - destinationDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(destinationConnection.getConfiguration()); - - final DestinationRead actualDestinationRead = destinationHandler.cloneDestination(destinationCloneRequestBody); - - assertEquals(expectedDestinationRead, actualDestinationRead); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/HealthCheckHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/HealthCheckHandlerTest.java deleted file mode 100644 index 8b010efa63ecc..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/HealthCheckHandlerTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import io.airbyte.api.model.generated.HealthCheckRead; -import io.airbyte.config.persistence.ConfigRepository; -import org.junit.jupiter.api.Test; - -class HealthCheckHandlerTest { - - @Test - void testDbHealthSucceed() { - final var mRepository = mock(ConfigRepository.class); - when(mRepository.healthCheck()).thenReturn(true); - - final HealthCheckHandler healthCheckHandler = new HealthCheckHandler(mRepository); - assertEquals(new HealthCheckRead().available(true), healthCheckHandler.health()); - } - - @Test - void testDbHealthFail() { - final var mRepository = mock(ConfigRepository.class); - when(mRepository.healthCheck()).thenReturn(false); - - final HealthCheckHandler healthCheckHandler = new HealthCheckHandler(mRepository); - assertEquals(new HealthCheckRead().available(false), healthCheckHandler.health()); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/JobHistoryHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/JobHistoryHandlerTest.java deleted file mode 100644 index 40465731df84e..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/JobHistoryHandlerTest.java +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableList; -import io.airbyte.api.model.generated.AttemptInfoRead; -import io.airbyte.api.model.generated.AttemptNormalizationStatusRead; -import io.airbyte.api.model.generated.AttemptNormalizationStatusReadList; -import io.airbyte.api.model.generated.AttemptRead; -import io.airbyte.api.model.generated.AttemptStreamStats; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.JobConfigType; -import io.airbyte.api.model.generated.JobDebugInfoRead; -import io.airbyte.api.model.generated.JobDebugRead; -import io.airbyte.api.model.generated.JobIdRequestBody; -import io.airbyte.api.model.generated.JobInfoLightRead; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.JobListRequestBody; -import io.airbyte.api.model.generated.JobRead; -import io.airbyte.api.model.generated.JobReadList; -import io.airbyte.api.model.generated.JobWithAttemptsRead; -import io.airbyte.api.model.generated.LogRead; -import io.airbyte.api.model.generated.Pagination; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.converters.JobConverter; -import io.airbyte.commons.server.helpers.ConnectionHelpers; -import io.airbyte.commons.server.helpers.DestinationDefinitionHelpers; -import io.airbyte.commons.server.helpers.DestinationHelpers; -import io.airbyte.commons.server.helpers.SourceDefinitionHelpers; -import io.airbyte.commons.server.helpers.SourceHelpers; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.JobCheckConnectionConfig; -import io.airbyte.config.JobConfig; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StreamSyncStats; -import io.airbyte.config.SyncStats; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.JobPersistence.AttemptStats; -import io.airbyte.persistence.job.JobPersistence.JobAttemptPair; -import io.airbyte.persistence.job.models.Attempt; -import io.airbyte.persistence.job.models.AttemptNormalizationStatus; -import io.airbyte.persistence.job.models.AttemptStatus; -import io.airbyte.persistence.job.models.Job; -import io.airbyte.persistence.job.models.JobStatus; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -@DisplayName("Job History Handler") -class JobHistoryHandlerTest { - - private static final long JOB_ID = 100L; - private static final int ATTEMPT_NUMBER = 0; - private static final String JOB_CONFIG_ID = "ef296385-6796-413f-ac1b-49c4caba3f2b"; - private static final JobStatus JOB_STATUS = JobStatus.SUCCEEDED; - private static final JobConfig.ConfigType CONFIG_TYPE = JobConfig.ConfigType.CHECK_CONNECTION_SOURCE; - private static final JobConfigType CONFIG_TYPE_FOR_API = JobConfigType.CHECK_CONNECTION_SOURCE; - private static final JobConfig JOB_CONFIG = new JobConfig() - .withConfigType(CONFIG_TYPE) - .withCheckConnection(new JobCheckConnectionConfig()); - private static final Path LOG_PATH = Path.of("log_path"); - private static final LogRead EMPTY_LOG_READ = new LogRead().logLines(new ArrayList<>()); - private static final long CREATED_AT = System.currentTimeMillis() / 1000; - - private static final AttemptStats ATTEMPT_STATS = new AttemptStats(new SyncStats().withBytesEmitted(10L).withRecordsEmitted(10L), - List.of( - new StreamSyncStats().withStreamNamespace("ns1").withStreamName("stream1") - .withStats(new SyncStats().withRecordsEmitted(5L).withBytesEmitted(5L)), - new StreamSyncStats().withStreamName("stream2") - .withStats(new SyncStats().withRecordsEmitted(5L).withBytesEmitted(5L)))); - - private static final io.airbyte.api.model.generated.AttemptStats ATTEMPT_STATS_API = new io.airbyte.api.model.generated.AttemptStats() - .bytesEmitted(10L).recordsEmitted(10L); - - private static final List ATTEMPT_STREAM_STATS = List.of( - new AttemptStreamStats().streamNamespace("ns1").streamName("stream1") - .stats(new io.airbyte.api.model.generated.AttemptStats().recordsEmitted(5L).bytesEmitted(5L)), - new AttemptStreamStats().streamName("stream2").stats(new io.airbyte.api.model.generated.AttemptStats().recordsEmitted(5L).bytesEmitted(5L))); - - private ConnectionsHandler connectionsHandler; - private SourceHandler sourceHandler; - private DestinationHandler destinationHandler; - private Job testJob; - private Attempt testJobAttempt; - private JobPersistence jobPersistence; - private JobHistoryHandler jobHistoryHandler; - - private static JobRead toJobInfo(final Job job) { - return new JobRead().id(job.getId()) - .configId(job.getScope()) - .status(Enums.convertTo(job.getStatus(), io.airbyte.api.model.generated.JobStatus.class)) - .configType(Enums.convertTo(job.getConfigType(), io.airbyte.api.model.generated.JobConfigType.class)) - .createdAt(job.getCreatedAtInSecond()) - .updatedAt(job.getUpdatedAtInSecond()); - - } - - private static JobDebugRead toDebugJobInfo(final Job job) { - return new JobDebugRead().id(job.getId()) - .configId(job.getScope()) - .status(Enums.convertTo(job.getStatus(), io.airbyte.api.model.generated.JobStatus.class)) - .configType(Enums.convertTo(job.getConfigType(), io.airbyte.api.model.generated.JobConfigType.class)) - .sourceDefinition(null) - .destinationDefinition(null); - - } - - private static List toAttemptInfoList(final List attempts) { - final List attemptReads = attempts.stream().map(JobHistoryHandlerTest::toAttemptRead).collect(Collectors.toList()); - - final Function toAttemptInfoRead = (AttemptRead a) -> new AttemptInfoRead().attempt(a).logs(EMPTY_LOG_READ); - return attemptReads.stream().map(toAttemptInfoRead).collect(Collectors.toList()); - } - - private static AttemptRead toAttemptRead(final Attempt a) { - return new AttemptRead() - .id((long) a.getAttemptNumber()) - .status(Enums.convertTo(a.getStatus(), io.airbyte.api.model.generated.AttemptStatus.class)) - .createdAt(a.getCreatedAtInSecond()) - .updatedAt(a.getUpdatedAtInSecond()) - .endedAt(a.getEndedAtInSecond().orElse(null)); - } - - private static Attempt createAttempt(final long jobId, final long timestamps, final AttemptStatus status) { - return new Attempt(ATTEMPT_NUMBER, jobId, LOG_PATH, null, null, status, null, null, timestamps, timestamps, timestamps); - } - - @BeforeEach - void setUp() { - testJobAttempt = createAttempt(JOB_ID, CREATED_AT, AttemptStatus.SUCCEEDED); - testJob = new Job(JOB_ID, JOB_CONFIG.getConfigType(), JOB_CONFIG_ID, JOB_CONFIG, ImmutableList.of(testJobAttempt), JOB_STATUS, null, CREATED_AT, - CREATED_AT); - - connectionsHandler = mock(ConnectionsHandler.class); - sourceHandler = mock(SourceHandler.class); - destinationHandler = mock(DestinationHandler.class); - jobPersistence = mock(JobPersistence.class); - final SourceDefinitionsHandler sourceDefinitionsHandler = mock(SourceDefinitionsHandler.class); - final DestinationDefinitionsHandler destinationDefinitionsHandler = mock(DestinationDefinitionsHandler.class); - final AirbyteVersion airbyteVersion = mock(AirbyteVersion.class); - jobHistoryHandler = new JobHistoryHandler(jobPersistence, WorkerEnvironment.DOCKER, LogConfigs.EMPTY, connectionsHandler, sourceHandler, - sourceDefinitionsHandler, destinationHandler, destinationDefinitionsHandler, airbyteVersion); - } - - @Nested - @DisplayName("When listing jobs") - class ListJobs { - - @Test - @DisplayName("Should return jobs with/without attempts in descending order") - void testListJobs() throws IOException { - final var successfulJob = testJob; - final int pagesize = 25; - final int rowOffset = 0; - - final var jobId2 = JOB_ID + 100; - final var createdAt2 = CREATED_AT + 1000; - final var latestJobNoAttempt = - new Job(jobId2, JOB_CONFIG.getConfigType(), JOB_CONFIG_ID, JOB_CONFIG, Collections.emptyList(), JobStatus.PENDING, - null, createdAt2, createdAt2); - - when(jobPersistence.listJobs(Set.of(Enums.convertTo(CONFIG_TYPE_FOR_API, ConfigType.class)), JOB_CONFIG_ID, pagesize, rowOffset)) - .thenReturn(List.of(latestJobNoAttempt, successfulJob)); - when(jobPersistence.getJobCount(Set.of(Enums.convertTo(CONFIG_TYPE_FOR_API, ConfigType.class)), JOB_CONFIG_ID)).thenReturn(2L); - when(jobPersistence.getAttemptStats(List.of(200L, 100L))).thenReturn(Map.of( - new JobAttemptPair(100, 0), ATTEMPT_STATS, - new JobAttemptPair(jobId2, 0), ATTEMPT_STATS)); - - final var requestBody = new JobListRequestBody() - .configTypes(Collections.singletonList(CONFIG_TYPE_FOR_API)) - .configId(JOB_CONFIG_ID) - .pagination(new Pagination().pageSize(pagesize).rowOffset(rowOffset)); - final var jobReadList = jobHistoryHandler.listJobsFor(requestBody); - - final var expAttemptRead = toAttemptRead(testJobAttempt).totalStats(ATTEMPT_STATS_API).streamStats(ATTEMPT_STREAM_STATS); - final var successfulJobWithAttemptRead = new JobWithAttemptsRead().job(toJobInfo(successfulJob)).attempts(ImmutableList.of(expAttemptRead)); - final var latestJobWithAttemptRead = new JobWithAttemptsRead().job(toJobInfo(latestJobNoAttempt)).attempts(Collections.emptyList()); - final JobReadList expectedJobReadList = - new JobReadList().jobs(List.of(latestJobWithAttemptRead, successfulJobWithAttemptRead)).totalJobCount(2L); - - assertEquals(expectedJobReadList, jobReadList); - } - - @Test - @DisplayName("Should return jobs in descending order regardless of type") - void testListJobsFor() throws IOException { - final var firstJob = testJob; - final int pagesize = 25; - final int rowOffset = 0; - - final var secondJobId = JOB_ID + 100; - final var createdAt2 = CREATED_AT + 1000; - final var secondJobAttempt = createAttempt(secondJobId, createdAt2, AttemptStatus.SUCCEEDED); - final var secondJob = new Job(secondJobId, ConfigType.DISCOVER_SCHEMA, JOB_CONFIG_ID, JOB_CONFIG, ImmutableList.of(secondJobAttempt), - JobStatus.SUCCEEDED, null, createdAt2, createdAt2); - - final Set configTypes = Set.of( - Enums.convertTo(CONFIG_TYPE_FOR_API, ConfigType.class), - Enums.convertTo(JobConfigType.SYNC, ConfigType.class), - Enums.convertTo(JobConfigType.DISCOVER_SCHEMA, ConfigType.class)); - - final var latestJobId = secondJobId + 100; - final var createdAt3 = createdAt2 + 1000; - final var latestJob = - new Job(latestJobId, ConfigType.SYNC, JOB_CONFIG_ID, JOB_CONFIG, Collections.emptyList(), JobStatus.PENDING, null, createdAt3, createdAt3); - - when(jobPersistence.listJobs(configTypes, JOB_CONFIG_ID, pagesize, rowOffset)).thenReturn(List.of(latestJob, secondJob, firstJob)); - when(jobPersistence.getJobCount(configTypes, JOB_CONFIG_ID)).thenReturn(3L); - when(jobPersistence.getAttemptStats(List.of(300L, 200L, 100L))).thenReturn(Map.of( - new JobAttemptPair(100, 0), ATTEMPT_STATS, - new JobAttemptPair(secondJobId, 0), ATTEMPT_STATS, - new JobAttemptPair(latestJobId, 0), ATTEMPT_STATS)); - - final JobListRequestBody requestBody = new JobListRequestBody() - .configTypes(List.of(CONFIG_TYPE_FOR_API, JobConfigType.SYNC, JobConfigType.DISCOVER_SCHEMA)) - .configId(JOB_CONFIG_ID) - .pagination(new Pagination().pageSize(pagesize).rowOffset(rowOffset)); - final JobReadList jobReadList = jobHistoryHandler.listJobsFor(requestBody); - - final var firstJobWithAttemptRead = - new JobWithAttemptsRead().job(toJobInfo(firstJob)) - .attempts(ImmutableList.of(toAttemptRead(testJobAttempt).totalStats(ATTEMPT_STATS_API).streamStats(ATTEMPT_STREAM_STATS))); - final var secondJobWithAttemptRead = - new JobWithAttemptsRead().job(toJobInfo(secondJob)) - .attempts(ImmutableList.of(toAttemptRead(secondJobAttempt).totalStats(ATTEMPT_STATS_API).streamStats(ATTEMPT_STREAM_STATS))); - final var latestJobWithAttemptRead = new JobWithAttemptsRead().job(toJobInfo(latestJob)).attempts(Collections.emptyList()); - final JobReadList expectedJobReadList = - new JobReadList().jobs(List.of(latestJobWithAttemptRead, secondJobWithAttemptRead, firstJobWithAttemptRead)).totalJobCount(3L); - - assertEquals(expectedJobReadList, jobReadList); - } - - @Test - @DisplayName("Should return jobs including specified job id") - void testListJobsIncludingJobId() throws IOException { - final var successfulJob = testJob; - final int pagesize = 25; - final int rowOffset = 0; - - final var jobId2 = JOB_ID + 100; - final var createdAt2 = CREATED_AT + 1000; - final var latestJobNoAttempt = - new Job(jobId2, JOB_CONFIG.getConfigType(), JOB_CONFIG_ID, JOB_CONFIG, Collections.emptyList(), JobStatus.PENDING, - null, createdAt2, createdAt2); - - when(jobPersistence.listJobsIncludingId(Set.of(Enums.convertTo(CONFIG_TYPE_FOR_API, ConfigType.class)), JOB_CONFIG_ID, jobId2, pagesize)) - .thenReturn(List.of(latestJobNoAttempt, successfulJob)); - when(jobPersistence.getJobCount(Set.of(Enums.convertTo(CONFIG_TYPE_FOR_API, ConfigType.class)), JOB_CONFIG_ID)).thenReturn(2L); - when(jobPersistence.getAttemptStats(List.of(200L, 100L))).thenReturn(Map.of( - new JobAttemptPair(100, 0), ATTEMPT_STATS, - new JobAttemptPair(jobId2, 0), ATTEMPT_STATS)); - - final var requestBody = new JobListRequestBody() - .configTypes(Collections.singletonList(CONFIG_TYPE_FOR_API)) - .configId(JOB_CONFIG_ID) - .includingJobId(jobId2) - .pagination(new Pagination().pageSize(pagesize).rowOffset(rowOffset)); - final var jobReadList = jobHistoryHandler.listJobsFor(requestBody); - - final var successfulJobWithAttemptRead = new JobWithAttemptsRead().job(toJobInfo(successfulJob)).attempts(ImmutableList.of(toAttemptRead( - testJobAttempt).totalStats(ATTEMPT_STATS_API).streamStats(ATTEMPT_STREAM_STATS))); - final var latestJobWithAttemptRead = new JobWithAttemptsRead().job(toJobInfo(latestJobNoAttempt)).attempts(Collections.emptyList()); - final JobReadList expectedJobReadList = - new JobReadList().jobs(List.of(latestJobWithAttemptRead, successfulJobWithAttemptRead)).totalJobCount(2L); - - assertEquals(expectedJobReadList, jobReadList); - } - - } - - @Test - @DisplayName("Should return the right job info") - void testGetJobInfo() throws IOException { - when(jobPersistence.getJob(JOB_ID)).thenReturn(testJob); - - final JobIdRequestBody requestBody = new JobIdRequestBody().id(JOB_ID); - final JobInfoRead jobInfoActual = jobHistoryHandler.getJobInfo(requestBody); - - final JobInfoRead exp = new JobInfoRead().job(toJobInfo(testJob)).attempts(toAttemptInfoList(ImmutableList.of(testJobAttempt))); - - assertEquals(exp, jobInfoActual); - } - - @Test - @DisplayName("Should return the right job info without attempt information") - void testGetJobInfoLight() throws IOException { - when(jobPersistence.getJob(JOB_ID)).thenReturn(testJob); - - final JobIdRequestBody requestBody = new JobIdRequestBody().id(JOB_ID); - final JobInfoLightRead jobInfoLightActual = jobHistoryHandler.getJobInfoLight(requestBody); - - final JobInfoLightRead exp = new JobInfoLightRead().job(toJobInfo(testJob)); - - assertEquals(exp, jobInfoLightActual); - } - - @Test - @DisplayName("Should return the right info to debug this job") - void testGetDebugJobInfo() throws IOException, JsonValidationException, ConfigNotFoundException, URISyntaxException { - final StandardSourceDefinition standardSourceDefinition = SourceDefinitionHelpers.generateSourceDefinition(); - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceRead sourceRead = SourceHelpers.getSourceRead(source, standardSourceDefinition); - - final StandardDestinationDefinition standardDestinationDefinition = DestinationDefinitionHelpers.generateDestination(); - final DestinationConnection destination = DestinationHelpers.generateDestination(UUID.randomUUID()); - final DestinationRead destinationRead = DestinationHelpers.getDestinationRead(destination, standardDestinationDefinition); - - final StandardSync standardSync = ConnectionHelpers.generateSyncWithSourceId(source.getSourceId()); - final ConnectionRead connectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - when(connectionsHandler.getConnection(UUID.fromString(testJob.getScope()))).thenReturn(connectionRead); - - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody(); - sourceIdRequestBody.setSourceId(connectionRead.getSourceId()); - when(sourceHandler.getSource(sourceIdRequestBody)).thenReturn(sourceRead); - - final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody(); - destinationIdRequestBody.setDestinationId(connectionRead.getDestinationId()); - when(destinationHandler.getDestination(destinationIdRequestBody)).thenReturn(destinationRead); - when(jobPersistence.getJob(JOB_ID)).thenReturn(testJob); - when(jobPersistence.getAttemptStats(anyLong(), anyInt())).thenReturn(ATTEMPT_STATS); - - final JobIdRequestBody requestBody = new JobIdRequestBody().id(JOB_ID); - final JobDebugInfoRead jobDebugInfoActual = jobHistoryHandler.getJobDebugInfo(requestBody); - final List attemptInfoReads = toAttemptInfoList(ImmutableList.of(testJobAttempt)); - attemptInfoReads.forEach(read -> read.getAttempt().totalStats(ATTEMPT_STATS_API).streamStats(ATTEMPT_STREAM_STATS)); - final JobDebugInfoRead exp = new JobDebugInfoRead().job(toDebugJobInfo(testJob)).attempts(attemptInfoReads); - - assertEquals(exp, jobDebugInfoActual); - } - - @Test - @DisplayName("Should return the latest running sync job") - void testGetLatestRunningSyncJob() throws IOException { - final var connectionId = UUID.randomUUID(); - - final var olderRunningJobId = JOB_ID + 100; - final var olderRunningCreatedAt = CREATED_AT + 1000; - final var olderRunningJobAttempt = createAttempt(olderRunningJobId, olderRunningCreatedAt, AttemptStatus.RUNNING); - final var olderRunningJob = new Job(olderRunningJobId, ConfigType.SYNC, JOB_CONFIG_ID, - JOB_CONFIG, ImmutableList.of(olderRunningJobAttempt), - JobStatus.RUNNING, null, olderRunningCreatedAt, olderRunningCreatedAt); - - // expect that we return the newer of the two running jobs. this should not happen in the real - // world but might as - // well test that we handle it properly. - final var newerRunningJobId = JOB_ID + 200; - final var newerRunningCreatedAt = CREATED_AT + 2000; - final var newerRunningJobAttempt = createAttempt(newerRunningJobId, newerRunningCreatedAt, AttemptStatus.RUNNING); - final var newerRunningJob = new Job(newerRunningJobId, ConfigType.SYNC, JOB_CONFIG_ID, - JOB_CONFIG, ImmutableList.of(newerRunningJobAttempt), - JobStatus.RUNNING, null, newerRunningCreatedAt, newerRunningCreatedAt); - - when(jobPersistence.listJobsForConnectionWithStatuses( - connectionId, - Collections.singleton(ConfigType.SYNC), - JobStatus.NON_TERMINAL_STATUSES)).thenReturn(List.of(newerRunningJob, olderRunningJob)); - - final Optional expectedJob = Optional.of(JobConverter.getJobRead(newerRunningJob)); - final Optional actualJob = jobHistoryHandler.getLatestRunningSyncJob(connectionId); - - assertEquals(expectedJob, actualJob); - } - - @Test - @DisplayName("Should return an empty optional if no running sync job") - void testGetLatestRunningSyncJobWhenNone() throws IOException { - final var connectionId = UUID.randomUUID(); - - when(jobPersistence.listJobsForConnectionWithStatuses( - connectionId, - Collections.singleton(ConfigType.SYNC), - JobStatus.NON_TERMINAL_STATUSES)).thenReturn(Collections.emptyList()); - - final Optional actual = jobHistoryHandler.getLatestRunningSyncJob(connectionId); - - assertTrue(actual.isEmpty()); - } - - @Test - @DisplayName("Should return the latest sync job") - void testGetLatestSyncJob() throws IOException { - final var connectionId = UUID.randomUUID(); - - // expect the newest job overall to be returned, even if it is failed - final var newerFailedJobId = JOB_ID + 200; - final var newerFailedCreatedAt = CREATED_AT + 2000; - final var newerFailedJobAttempt = createAttempt(newerFailedJobId, newerFailedCreatedAt, AttemptStatus.FAILED); - final var newerFailedJob = new Job(newerFailedJobId, ConfigType.SYNC, JOB_CONFIG_ID, - JOB_CONFIG, ImmutableList.of(newerFailedJobAttempt), - JobStatus.RUNNING, null, newerFailedCreatedAt, newerFailedCreatedAt); - - when(jobPersistence.getLastSyncJob(connectionId)).thenReturn(Optional.of(newerFailedJob)); - - final Optional expectedJob = Optional.of(JobConverter.getJobRead(newerFailedJob)); - final Optional actualJob = jobHistoryHandler.getLatestSyncJob(connectionId); - - assertEquals(expectedJob, actualJob); - } - - @Test - @DisplayName("Should have compatible config enums") - void testEnumConversion() { - assertTrue(Enums.isCompatible(JobConfig.ConfigType.class, JobConfigType.class)); - } - - @Test - @DisplayName("Should return attempt normalization info for the job") - void testGetAttemptNormalizationStatuses() throws IOException { - - final AttemptNormalizationStatus databaseReadResult = new AttemptNormalizationStatus(1, Optional.of(10L), /* hasNormalizationFailed= */ false); - - when(jobPersistence.getAttemptNormalizationStatusesForJob(JOB_ID)).thenReturn(List.of(databaseReadResult)); - - final AttemptNormalizationStatusReadList expectedStatus = new AttemptNormalizationStatusReadList().attemptNormalizationStatuses( - List.of(new AttemptNormalizationStatusRead().attemptNumber(1).hasRecordsCommitted(true).hasNormalizationFailed(false).recordsCommitted(10L))); - - assertEquals(expectedStatus, jobHistoryHandler.getAttemptNormalizationStatuses(new JobIdRequestBody().id(JOB_ID))); - - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/LogsHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/LogsHandlerTest.java deleted file mode 100644 index eb19d78fba134..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/LogsHandlerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import io.airbyte.api.model.generated.LogType; -import io.airbyte.api.model.generated.LogsRequestBody; -import io.airbyte.config.Configs; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.helpers.LogClientSingleton; -import io.airbyte.config.helpers.LogConfigs; -import java.io.File; -import java.nio.file.Path; -import org.junit.jupiter.api.Test; - -class LogsHandlerTest { - - @Test - void testServerLogs() { - final Configs configs = mock(Configs.class); - when(configs.getWorkspaceRoot()).thenReturn(Path.of("/workspace")); - when(configs.getWorkerEnvironment()).thenReturn(WorkerEnvironment.DOCKER); - when(configs.getLogConfigs()).thenReturn(LogConfigs.EMPTY); - - final File expected = Path.of(String.format("/workspace/server/logs/%s", LogClientSingleton.LOG_FILENAME)).toFile(); - final File actual = new LogsHandler(configs).getLogs(new LogsRequestBody().logType(LogType.SERVER)); - - assertEquals(expected, actual); - } - - @Test - void testSchedulerLogs() { - final Configs configs = mock(Configs.class); - when(configs.getWorkspaceRoot()).thenReturn(Path.of("/workspace")); - when(configs.getWorkerEnvironment()).thenReturn(WorkerEnvironment.DOCKER); - when(configs.getLogConfigs()).thenReturn(LogConfigs.EMPTY); - - final File expected = Path.of(String.format("/workspace/scheduler/logs/%s", LogClientSingleton.LOG_FILENAME)).toFile(); - final File actual = new LogsHandler(configs).getLogs(new LogsRequestBody().logType(LogType.SCHEDULER)); - - assertEquals(expected, actual); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OAuthHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OAuthHandlerTest.java deleted file mode 100644 index a3ca6b98aa829..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OAuthHandlerTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.analytics.TrackingClient; -import io.airbyte.api.model.generated.SetInstancewideDestinationOauthParamsRequestBody; -import io.airbyte.api.model.generated.SetInstancewideSourceOauthParamsRequestBody; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.DestinationOAuthParameter; -import io.airbyte.config.SourceOAuthParameter; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.net.http.HttpClient; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -class OAuthHandlerTest { - - private ConfigRepository configRepository; - private OAuthHandler handler; - private TrackingClient trackingClient; - private HttpClient httpClient; - private SecretsRepositoryReader secretsRepositoryReader; - private static final String CLIENT_ID = "123"; - private static final String CLIENT_ID_KEY = "client_id"; - private static final String CLIENT_SECRET_KEY = "client_secret"; - private static final String CLIENT_SECRET = "hunter2"; - - @BeforeEach - public void init() { - configRepository = Mockito.mock(ConfigRepository.class); - trackingClient = mock(TrackingClient.class); - httpClient = Mockito.mock(HttpClient.class); - secretsRepositoryReader = mock(SecretsRepositoryReader.class); - handler = new OAuthHandler(configRepository, httpClient, trackingClient, secretsRepositoryReader); - } - - @Test - void setSourceInstancewideOauthParams() throws JsonValidationException, IOException { - final UUID sourceDefId = UUID.randomUUID(); - final Map params = new HashMap<>(); - params.put(CLIENT_ID_KEY, CLIENT_ID); - params.put(CLIENT_SECRET_KEY, CLIENT_SECRET); - - final SetInstancewideSourceOauthParamsRequestBody actualRequest = new SetInstancewideSourceOauthParamsRequestBody() - .sourceDefinitionId(sourceDefId) - .params(params); - - handler.setSourceInstancewideOauthParams(actualRequest); - - final ArgumentCaptor argument = ArgumentCaptor.forClass(SourceOAuthParameter.class); - Mockito.verify(configRepository).writeSourceOAuthParam(argument.capture()); - assertEquals(Jsons.jsonNode(params), argument.getValue().getConfiguration()); - assertEquals(sourceDefId, argument.getValue().getSourceDefinitionId()); - } - - @Test - void resetSourceInstancewideOauthParams() throws JsonValidationException, IOException { - final UUID sourceDefId = UUID.randomUUID(); - final Map firstParams = new HashMap<>(); - firstParams.put(CLIENT_ID_KEY, CLIENT_ID); - firstParams.put(CLIENT_SECRET_KEY, CLIENT_SECRET); - final SetInstancewideSourceOauthParamsRequestBody firstRequest = new SetInstancewideSourceOauthParamsRequestBody() - .sourceDefinitionId(sourceDefId) - .params(firstParams); - handler.setSourceInstancewideOauthParams(firstRequest); - - final UUID oauthParameterId = UUID.randomUUID(); - when(configRepository.getSourceOAuthParamByDefinitionIdOptional(null, sourceDefId)) - .thenReturn(Optional.of(new SourceOAuthParameter().withOauthParameterId(oauthParameterId))); - - final Map secondParams = new HashMap<>(); - secondParams.put(CLIENT_ID_KEY, "456"); - secondParams.put(CLIENT_SECRET_KEY, "hunter3"); - final SetInstancewideSourceOauthParamsRequestBody secondRequest = new SetInstancewideSourceOauthParamsRequestBody() - .sourceDefinitionId(sourceDefId) - .params(secondParams); - handler.setSourceInstancewideOauthParams(secondRequest); - - final ArgumentCaptor argument = ArgumentCaptor.forClass(SourceOAuthParameter.class); - Mockito.verify(configRepository, Mockito.times(2)).writeSourceOAuthParam(argument.capture()); - final List capturedValues = argument.getAllValues(); - assertEquals(Jsons.jsonNode(firstParams), capturedValues.get(0).getConfiguration()); - assertEquals(Jsons.jsonNode(secondParams), capturedValues.get(1).getConfiguration()); - assertEquals(sourceDefId, capturedValues.get(0).getSourceDefinitionId()); - assertEquals(sourceDefId, capturedValues.get(1).getSourceDefinitionId()); - assertEquals(oauthParameterId, capturedValues.get(1).getOauthParameterId()); - } - - @Test - void setDestinationInstancewideOauthParams() throws JsonValidationException, IOException { - final UUID destinationDefId = UUID.randomUUID(); - final Map params = new HashMap<>(); - params.put(CLIENT_ID_KEY, CLIENT_ID); - params.put(CLIENT_SECRET_KEY, CLIENT_SECRET); - - final SetInstancewideDestinationOauthParamsRequestBody actualRequest = new SetInstancewideDestinationOauthParamsRequestBody() - .destinationDefinitionId(destinationDefId) - .params(params); - - handler.setDestinationInstancewideOauthParams(actualRequest); - - final ArgumentCaptor argument = ArgumentCaptor.forClass(DestinationOAuthParameter.class); - Mockito.verify(configRepository).writeDestinationOAuthParam(argument.capture()); - assertEquals(Jsons.jsonNode(params), argument.getValue().getConfiguration()); - assertEquals(destinationDefId, argument.getValue().getDestinationDefinitionId()); - } - - @Test - void resetDestinationInstancewideOauthParams() throws JsonValidationException, IOException { - final UUID destinationDefId = UUID.randomUUID(); - final Map firstParams = new HashMap<>(); - firstParams.put(CLIENT_ID_KEY, CLIENT_ID); - firstParams.put(CLIENT_SECRET_KEY, CLIENT_SECRET); - final SetInstancewideDestinationOauthParamsRequestBody firstRequest = new SetInstancewideDestinationOauthParamsRequestBody() - .destinationDefinitionId(destinationDefId) - .params(firstParams); - handler.setDestinationInstancewideOauthParams(firstRequest); - - final UUID oauthParameterId = UUID.randomUUID(); - when(configRepository.getDestinationOAuthParamByDefinitionIdOptional(null, destinationDefId)) - .thenReturn(Optional.of(new DestinationOAuthParameter().withOauthParameterId(oauthParameterId))); - - final Map secondParams = new HashMap<>(); - secondParams.put(CLIENT_ID_KEY, "456"); - secondParams.put(CLIENT_SECRET_KEY, "hunter3"); - final SetInstancewideDestinationOauthParamsRequestBody secondRequest = new SetInstancewideDestinationOauthParamsRequestBody() - .destinationDefinitionId(destinationDefId) - .params(secondParams); - handler.setDestinationInstancewideOauthParams(secondRequest); - - final ArgumentCaptor argument = ArgumentCaptor.forClass(DestinationOAuthParameter.class); - Mockito.verify(configRepository, Mockito.times(2)).writeDestinationOAuthParam(argument.capture()); - final List capturedValues = argument.getAllValues(); - assertEquals(Jsons.jsonNode(firstParams), capturedValues.get(0).getConfiguration()); - assertEquals(Jsons.jsonNode(secondParams), capturedValues.get(1).getConfiguration()); - assertEquals(destinationDefId, capturedValues.get(0).getDestinationDefinitionId()); - assertEquals(destinationDefId, capturedValues.get(1).getDestinationDefinitionId()); - assertEquals(oauthParameterId, capturedValues.get(1).getOauthParameterId()); - } - - @Test - void testBuildJsonPathFromOAuthFlowInitParameters() { - final Map> input = Map.ofEntries( - Map.entry("field1", List.of("1")), - Map.entry("field2", List.of("2", "3"))); - - final Map expected = Map.ofEntries( - Map.entry("field1", "$.1"), - Map.entry("field2", "$.2.3")); - - assertEquals(expected, handler.buildJsonPathFromOAuthFlowInitParameters(input)); - } - - @Test - void testGetOAuthInputConfiguration() { - final JsonNode hydratedConfig = Jsons.deserialize( - """ - { - "field1": "1", - "field2": "2", - "field3": { - "field3_1": "3_1", - "field3_2": "3_2" - } - } - """); - - final Map pathsToGet = Map.ofEntries( - Map.entry("field1", "$.field1"), - Map.entry("field3_1", "$.field3.field3_1"), - Map.entry("field3_2", "$.field3.field3_2"), - Map.entry("field4", "$.someNonexistentField")); - - final JsonNode expected = Jsons.deserialize( - """ - { - "field1": "1", - "field3_1": "3_1", - "field3_2": "3_2" - } - """); - - assertEquals(expected, handler.getOAuthInputConfiguration(hydratedConfig, pathsToGet)); - } - - @Test - void testGetOauthFromDBIfNeeded() { - final JsonNode fromInput = Jsons.deserialize( - """ - { - "testMask": "**********", - "testNotMask": "this", - "testOtherType": true - } - """); - - final JsonNode fromDb = Jsons.deserialize( - """ - { - "testMask": "mask", - "testNotMask": "notThis", - "testOtherType": true - } - """); - - final JsonNode expected = Jsons.deserialize( - """ - { - "testMask": "mask", - "testNotMask": "this", - "testOtherType": true - } - """); - - assertEquals(expected, handler.getOauthFromDBIfNeeded(fromDb, fromInput)); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OpenApiConfigHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OpenApiConfigHandlerTest.java deleted file mode 100644 index 14b2e734ed2ec..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OpenApiConfigHandlerTest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.*; - -import com.google.common.io.Files; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.List; -import org.junit.jupiter.api.Test; - -class OpenApiConfigHandlerTest { - - @Test - void testGetFile() throws IOException { - final List lines = Files.readLines(new OpenApiConfigHandler().getFile(), Charset.defaultCharset()); - assertTrue(lines.get(0).contains("openapi")); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OperationsHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OperationsHandlerTest.java deleted file mode 100644 index 84fc0f8280fbe..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/OperationsHandlerTest.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.OperationCreate; -import io.airbyte.api.model.generated.OperationIdRequestBody; -import io.airbyte.api.model.generated.OperationRead; -import io.airbyte.api.model.generated.OperationReadList; -import io.airbyte.api.model.generated.OperationUpdate; -import io.airbyte.api.model.generated.OperatorConfiguration; -import io.airbyte.api.model.generated.OperatorDbt; -import io.airbyte.api.model.generated.OperatorNormalization; -import io.airbyte.api.model.generated.OperatorNormalization.OptionEnum; -import io.airbyte.api.model.generated.OperatorType; -import io.airbyte.api.model.generated.OperatorWebhook; -import io.airbyte.api.model.generated.OperatorWebhook.WebhookTypeEnum; -import io.airbyte.api.model.generated.OperatorWebhookDbtCloud; -import io.airbyte.commons.enums.Enums; -import io.airbyte.config.OperatorNormalization.Option; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSyncOperation; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class OperationsHandlerTest { - - private static final String WEBHOOK_OPERATION_NAME = "fake-operation-name"; - private static final UUID WEBHOOK_CONFIG_ID = UUID.randomUUID(); - private static final UUID WEBHOOK_OPERATION_ID = UUID.randomUUID(); - private static final Integer DBT_CLOUD_WEBHOOK_ACCOUNT_ID = 123; - private static final Integer DBT_CLOUD_WEBHOOK_JOB_ID = 456; - private static final Integer NEW_DBT_CLOUD_WEBHOOK_ACCOUNT_ID = 789; - public static final String EXECUTION_BODY = "{\"cause\": \"airbyte\"}"; - public static final String EXECUTION_URL_TEMPLATE = "https://cloud.getdbt.com/api/v2/accounts/%d/jobs/%d/run/"; - private ConfigRepository configRepository; - private Supplier uuidGenerator; - private OperationsHandler operationsHandler; - private StandardSyncOperation standardSyncOperation; - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() throws IOException { - configRepository = mock(ConfigRepository.class); - uuidGenerator = mock(Supplier.class); - - operationsHandler = new OperationsHandler(configRepository, uuidGenerator); - standardSyncOperation = new StandardSyncOperation() - .withWorkspaceId(UUID.randomUUID()) - .withOperationId(UUID.randomUUID()) - .withName("presto to hudi") - .withOperatorType(io.airbyte.config.StandardSyncOperation.OperatorType.NORMALIZATION) - .withOperatorNormalization(new io.airbyte.config.OperatorNormalization().withOption(Option.BASIC)) - .withOperatorDbt(null) - .withTombstone(false); - } - - @Test - void testCreateOperation() throws JsonValidationException, ConfigNotFoundException, IOException { - when(uuidGenerator.get()).thenReturn(standardSyncOperation.getOperationId()); - - when(configRepository.getStandardSyncOperation(standardSyncOperation.getOperationId())).thenReturn(standardSyncOperation); - - final OperationCreate operationCreate = new OperationCreate() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .name(standardSyncOperation.getName()) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.NORMALIZATION) - .normalization(new OperatorNormalization().option(OptionEnum.BASIC))); - - final OperationRead actualOperationRead = operationsHandler.createOperation(operationCreate); - - final OperationRead expectedOperationRead = new OperationRead() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .operationId(standardSyncOperation.getOperationId()) - .name(standardSyncOperation.getName()) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.NORMALIZATION) - .normalization(new OperatorNormalization().option(OptionEnum.BASIC))); - - assertEquals(expectedOperationRead, actualOperationRead); - - verify(configRepository).writeStandardSyncOperation(standardSyncOperation); - } - - @Test - void testCreateWebhookOperation() throws JsonValidationException, ConfigNotFoundException, IOException { - when(uuidGenerator.get()).thenReturn(WEBHOOK_OPERATION_ID); - final OperatorWebhook webhookConfig = new OperatorWebhook() - .webhookConfigId(WEBHOOK_CONFIG_ID) - .webhookType(WebhookTypeEnum.DBTCLOUD) - .dbtCloud(new OperatorWebhookDbtCloud() - .accountId(DBT_CLOUD_WEBHOOK_ACCOUNT_ID) - .jobId(DBT_CLOUD_WEBHOOK_JOB_ID)); - final OperationCreate operationCreate = new OperationCreate() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .name(WEBHOOK_OPERATION_NAME) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.WEBHOOK).webhook(webhookConfig)); - - final StandardSyncOperation expectedPersistedOperation = new StandardSyncOperation() - .withWorkspaceId(standardSyncOperation.getWorkspaceId()) - .withOperationId(WEBHOOK_OPERATION_ID) - .withName(WEBHOOK_OPERATION_NAME) - .withOperatorType(StandardSyncOperation.OperatorType.WEBHOOK) - .withOperatorWebhook(new io.airbyte.config.OperatorWebhook() - .withWebhookConfigId(WEBHOOK_CONFIG_ID) - .withExecutionUrl(String.format(EXECUTION_URL_TEMPLATE, DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID)) - .withExecutionBody(EXECUTION_BODY)) - .withTombstone(false); - - when(configRepository.getStandardSyncOperation(WEBHOOK_OPERATION_ID)).thenReturn(expectedPersistedOperation); - - final OperationRead actualOperationRead = operationsHandler.createOperation(operationCreate); - - assertEquals(operationCreate.getWorkspaceId(), actualOperationRead.getWorkspaceId()); - assertEquals(WEBHOOK_OPERATION_ID, actualOperationRead.getOperationId()); - assertEquals(WEBHOOK_OPERATION_NAME, actualOperationRead.getName()); - assertEquals(OperatorType.WEBHOOK, actualOperationRead.getOperatorConfiguration().getOperatorType()); - - // NOTE: we expect the server to dual-write on read until the frontend moves to the new format. - final OperatorWebhook expectedWebhookConfigRead = - webhookConfig.executionUrl(String.format(EXECUTION_URL_TEMPLATE, DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID)).executionBody(EXECUTION_BODY); - assertEquals(expectedWebhookConfigRead, actualOperationRead.getOperatorConfiguration().getWebhook()); - - verify(configRepository).writeStandardSyncOperation(eq(expectedPersistedOperation)); - } - - @Test - void testUpdateOperation() throws JsonValidationException, ConfigNotFoundException, IOException { - final OperationUpdate operationUpdate = new OperationUpdate() - .operationId(standardSyncOperation.getOperationId()) - .name(standardSyncOperation.getName()) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.DBT) - .dbt(new OperatorDbt() - .gitRepoUrl("git_repo_url") - .gitRepoBranch("git_repo_branch") - .dockerImage("docker") - .dbtArguments("--full-refresh"))); - - final StandardSyncOperation updatedStandardSyncOperation = new StandardSyncOperation() - .withWorkspaceId(standardSyncOperation.getWorkspaceId()) - .withOperationId(standardSyncOperation.getOperationId()) - .withName(standardSyncOperation.getName()) - .withOperatorType(io.airbyte.config.StandardSyncOperation.OperatorType.DBT) - .withOperatorDbt(new io.airbyte.config.OperatorDbt() - .withGitRepoUrl("git_repo_url") - .withGitRepoBranch("git_repo_branch") - .withDockerImage("docker") - .withDbtArguments("--full-refresh")) - .withOperatorNormalization(null) - .withTombstone(false); - - when(configRepository.getStandardSyncOperation(standardSyncOperation.getOperationId())).thenReturn(standardSyncOperation) - .thenReturn(updatedStandardSyncOperation); - - final OperationRead actualOperationRead = operationsHandler.updateOperation(operationUpdate); - - final OperationRead expectedOperationRead = new OperationRead() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .operationId(standardSyncOperation.getOperationId()) - .name(standardSyncOperation.getName()) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.DBT) - .dbt(new OperatorDbt() - .gitRepoUrl("git_repo_url") - .gitRepoBranch("git_repo_branch") - .dockerImage("docker") - .dbtArguments("--full-refresh"))); - - assertEquals(expectedOperationRead, actualOperationRead); - - verify(configRepository).writeStandardSyncOperation(updatedStandardSyncOperation); - } - - @Test - void testUpdateWebhookOperation() throws JsonValidationException, ConfigNotFoundException, IOException { - when(uuidGenerator.get()).thenReturn(WEBHOOK_OPERATION_ID); - final OperatorWebhook webhookConfig = new OperatorWebhook() - .webhookConfigId(WEBHOOK_CONFIG_ID) - .webhookType(WebhookTypeEnum.DBTCLOUD) - .dbtCloud(new OperatorWebhookDbtCloud() - .accountId(NEW_DBT_CLOUD_WEBHOOK_ACCOUNT_ID) - .jobId(DBT_CLOUD_WEBHOOK_JOB_ID)); - final OperationUpdate operationUpdate = new OperationUpdate() - .name(WEBHOOK_OPERATION_NAME) - .operationId(WEBHOOK_OPERATION_ID) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.WEBHOOK).webhook(webhookConfig)); - - final var persistedWebhook = new io.airbyte.config.OperatorWebhook() - .withWebhookConfigId(WEBHOOK_CONFIG_ID) - .withExecutionUrl(String.format(EXECUTION_URL_TEMPLATE, DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID)) - .withExecutionBody(EXECUTION_BODY); - - final var updatedWebhook = new io.airbyte.config.OperatorWebhook() - .withWebhookConfigId(WEBHOOK_CONFIG_ID) - .withExecutionUrl(String.format(EXECUTION_URL_TEMPLATE, NEW_DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID)) - .withExecutionBody(EXECUTION_BODY); - - final StandardSyncOperation persistedOperation = new StandardSyncOperation() - .withWorkspaceId(standardSyncOperation.getWorkspaceId()) - .withOperationId(WEBHOOK_OPERATION_ID) - .withName(WEBHOOK_OPERATION_NAME) - .withOperatorType(StandardSyncOperation.OperatorType.WEBHOOK) - .withOperatorWebhook(persistedWebhook); - - final StandardSyncOperation updatedOperation = new StandardSyncOperation() - .withWorkspaceId(standardSyncOperation.getWorkspaceId()) - .withOperationId(WEBHOOK_OPERATION_ID) - .withName(WEBHOOK_OPERATION_NAME) - .withOperatorType(StandardSyncOperation.OperatorType.WEBHOOK) - .withOperatorWebhook(updatedWebhook); - - when(configRepository.getStandardSyncOperation(WEBHOOK_OPERATION_ID)).thenReturn(persistedOperation).thenReturn(updatedOperation); - - final OperationRead actualOperationRead = operationsHandler.updateOperation(operationUpdate); - - assertEquals(WEBHOOK_OPERATION_ID, actualOperationRead.getOperationId()); - assertEquals(WEBHOOK_OPERATION_NAME, actualOperationRead.getName()); - assertEquals(OperatorType.WEBHOOK, actualOperationRead.getOperatorConfiguration().getOperatorType()); - final OperatorWebhook expectedWebhookConfigRead = - webhookConfig.executionUrl(String.format(EXECUTION_URL_TEMPLATE, NEW_DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID)).executionBody(EXECUTION_BODY); - assertEquals(expectedWebhookConfigRead, actualOperationRead.getOperatorConfiguration().getWebhook()); - - verify(configRepository) - .writeStandardSyncOperation(persistedOperation.withOperatorWebhook(persistedOperation.getOperatorWebhook().withExecutionUrl( - String.format(EXECUTION_URL_TEMPLATE, NEW_DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID)))); - } - - @Test - void testGetOperation() throws JsonValidationException, ConfigNotFoundException, IOException { - when(configRepository.getStandardSyncOperation(standardSyncOperation.getOperationId())).thenReturn(standardSyncOperation); - - final OperationIdRequestBody operationIdRequestBody = new OperationIdRequestBody().operationId(standardSyncOperation.getOperationId()); - final OperationRead actualOperationRead = operationsHandler.getOperation(operationIdRequestBody); - - final OperationRead expectedOperationRead = generateOperationRead(); - - assertEquals(expectedOperationRead, actualOperationRead); - } - - private OperationRead generateOperationRead() { - return new OperationRead() - .workspaceId(standardSyncOperation.getWorkspaceId()) - .operationId(standardSyncOperation.getOperationId()) - .name(standardSyncOperation.getName()) - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.NORMALIZATION) - .normalization(new OperatorNormalization().option(OptionEnum.BASIC))); - } - - @Test - void testListOperationsForConnection() throws JsonValidationException, ConfigNotFoundException, IOException { - final UUID connectionId = UUID.randomUUID(); - - when(configRepository.getStandardSync(connectionId)) - .thenReturn(new StandardSync() - .withOperationIds(List.of(standardSyncOperation.getOperationId()))); - - when(configRepository.getStandardSyncOperation(standardSyncOperation.getOperationId())) - .thenReturn(standardSyncOperation); - - when(configRepository.listStandardSyncOperations()) - .thenReturn(List.of(standardSyncOperation)); - - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(connectionId); - final OperationReadList actualOperationReadList = operationsHandler.listOperationsForConnection(connectionIdRequestBody); - - assertEquals(generateOperationRead(), actualOperationReadList.getOperations().get(0)); - } - - @Test - void testDeleteOperation() throws IOException { - final OperationIdRequestBody operationIdRequestBody = new OperationIdRequestBody().operationId(standardSyncOperation.getOperationId()); - - final OperationsHandler spiedOperationsHandler = spy(operationsHandler); - - spiedOperationsHandler.deleteOperation(operationIdRequestBody); - - verify(configRepository).deleteStandardSyncOperation(standardSyncOperation.getOperationId()); - } - - @Test - void testDeleteOperationsForConnection() throws JsonValidationException, IOException, ConfigNotFoundException { - final UUID syncConnectionId = UUID.randomUUID(); - final UUID otherConnectionId = UUID.randomUUID(); - final UUID operationId = UUID.randomUUID(); - final UUID remainingOperationId = UUID.randomUUID(); - final List toDelete = Stream.of(standardSyncOperation.getOperationId(), operationId).collect(Collectors.toList()); - final StandardSync sync = new StandardSync() - .withConnectionId(syncConnectionId) - .withOperationIds(List.of(standardSyncOperation.getOperationId(), operationId, remainingOperationId)); - when(configRepository.listStandardSyncs()).thenReturn(List.of( - sync, - new StandardSync() - .withConnectionId(otherConnectionId) - .withOperationIds(List.of(standardSyncOperation.getOperationId())))); - final StandardSyncOperation operation = new StandardSyncOperation().withOperationId(operationId); - final StandardSyncOperation remainingOperation = new StandardSyncOperation().withOperationId(remainingOperationId); - when(configRepository.getStandardSyncOperation(operationId)).thenReturn(operation); - when(configRepository.getStandardSyncOperation(remainingOperationId)).thenReturn(remainingOperation); - when(configRepository.getStandardSyncOperation(standardSyncOperation.getOperationId())).thenReturn(standardSyncOperation); - - // first, test that a remaining operation results in proper call - operationsHandler.deleteOperationsForConnection(sync, toDelete); - verify(configRepository).writeStandardSyncOperation(operation.withTombstone(true)); - verify(configRepository).updateConnectionOperationIds(syncConnectionId, Collections.singleton(remainingOperationId)); - - // next, test that removing all operations results in proper call - toDelete.add(remainingOperationId); - operationsHandler.deleteOperationsForConnection(sync, toDelete); - verify(configRepository).updateConnectionOperationIds(syncConnectionId, Collections.emptySet()); - } - - @Test - void testEnumConversion() { - assertTrue(Enums.isCompatible(io.airbyte.api.model.generated.OperatorType.class, io.airbyte.config.StandardSyncOperation.OperatorType.class)); - assertTrue(Enums.isCompatible(io.airbyte.api.model.generated.OperatorNormalization.OptionEnum.class, - io.airbyte.config.OperatorNormalization.Option.class)); - } - - @Test - void testDbtCloudRegex() { - // Validate that a non-url is rejected. - assertThrows(IllegalArgumentException.class, () -> checkDbtCloudUrl("not-a-url")); - // Validate that the URL is anchored to the beginning. - assertThrows(IllegalArgumentException.class, - () -> checkDbtCloudUrl("some-nonsense-" + String.format(EXECUTION_URL_TEMPLATE, DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID))); - // Validate that the URL is anchored to the end. - assertThrows(IllegalArgumentException.class, - () -> checkDbtCloudUrl(String.format(EXECUTION_URL_TEMPLATE, DBT_CLOUD_WEBHOOK_ACCOUNT_ID, - DBT_CLOUD_WEBHOOK_JOB_ID) + "-some-nonsense")); - // Validate that the account id must be an integer. - assertThrows(IllegalArgumentException.class, () -> checkDbtCloudUrl("https://cloud.getdbt.com/api/v2/accounts/abc/jobs/123/run/")); - // Validate that the job id must be an integer. - assertThrows(IllegalArgumentException.class, () -> checkDbtCloudUrl("https://cloud.getdbt.com/api/v2/accounts/123/jobs/abc/run/")); - } - - private void checkDbtCloudUrl(final String urlToCheck) throws JsonValidationException, ConfigNotFoundException, IOException { - final StandardSyncOperation persistedOperation = new StandardSyncOperation() - .withWorkspaceId(standardSyncOperation.getWorkspaceId()) - .withOperationId(WEBHOOK_OPERATION_ID) - .withName(WEBHOOK_OPERATION_NAME) - .withOperatorType(StandardSyncOperation.OperatorType.WEBHOOK) - .withOperatorWebhook(new io.airbyte.config.OperatorWebhook() - .withWebhookConfigId(WEBHOOK_CONFIG_ID) - .withExecutionUrl(urlToCheck) - .withExecutionBody(EXECUTION_BODY)) - .withTombstone(false); - when(configRepository.getStandardSyncOperation(WEBHOOK_OPERATION_ID)).thenReturn(persistedOperation); - - final OperationIdRequestBody operationIdRequestBody = new OperationIdRequestBody().operationId(WEBHOOK_OPERATION_ID); - operationsHandler.getOperation(operationIdRequestBody); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SchedulerHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SchedulerHandlerTest.java deleted file mode 100644 index be7a71f93adfa..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SchedulerHandlerTest.java +++ /dev/null @@ -1,1248 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import com.google.common.collect.Lists; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.model.generated.CatalogDiff; -import io.airbyte.api.model.generated.CheckConnectionRead; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; -import io.airbyte.api.model.generated.ConnectionStatus; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.DestinationCoreConfig; -import io.airbyte.api.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.DestinationDefinitionSpecificationRead; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationUpdate; -import io.airbyte.api.model.generated.FieldTransform; -import io.airbyte.api.model.generated.JobIdRequestBody; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.NonBreakingChangesPreference; -import io.airbyte.api.model.generated.SourceCoreConfig; -import io.airbyte.api.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.SourceDefinitionSpecificationRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRequestBody; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceUpdate; -import io.airbyte.api.model.generated.StreamTransform; -import io.airbyte.api.model.generated.StreamTransform.TransformTypeEnum; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.features.EnvVariableFeatureFlags; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.lang.Exceptions; -import io.airbyte.commons.server.converters.ConfigurationUpdate; -import io.airbyte.commons.server.converters.JobConverter; -import io.airbyte.commons.server.errors.ValueConflictKnownException; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.helpers.DestinationHelpers; -import io.airbyte.commons.server.helpers.SourceHelpers; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.commons.server.scheduler.SynchronousJobMetadata; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.temporal.ErrorCode; -import io.airbyte.commons.temporal.TemporalClient.ManualOperationResult; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorCatalog; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardCheckConnectionOutput; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.WebUrlHelper; -import io.airbyte.persistence.job.models.Job; -import io.airbyte.persistence.job.models.JobStatus; -import io.airbyte.protocol.models.AirbyteCatalog; -import io.airbyte.protocol.models.CatalogHelpers; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.protocol.models.Field; -import io.airbyte.protocol.models.JsonSchemaType; -import io.airbyte.protocol.models.StreamDescriptor; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.net.URI; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -@SuppressWarnings("unchecked") -class SchedulerHandlerTest { - - private static final String SOURCE_DOCKER_REPO = "srcimage"; - private static final String SOURCE_DOCKER_TAG = "tag"; - private static final String SOURCE_DOCKER_IMAGE = SOURCE_DOCKER_REPO + ":" + SOURCE_DOCKER_TAG; - private static final String SOURCE_PROTOCOL_VERSION = "0.4.5"; - - private static final String DESTINATION_DOCKER_REPO = "dstimage"; - private static final String DESTINATION_DOCKER_TAG = "tag"; - private static final String DESTINATION_DOCKER_IMAGE = DESTINATION_DOCKER_REPO + ":" + DESTINATION_DOCKER_TAG; - private static final String DESTINATION_PROTOCOL_VERSION = "0.7.9"; - private static final String NAME = "name"; - private static final String DOGS = "dogs"; - private static final String SHOES = "shoes"; - private static final String SKU = "sku"; - private static final String CONNECTION_URL = "connection_url"; - - private static final AirbyteCatalog airbyteCatalog = CatalogHelpers.createAirbyteCatalog(SHOES, - Field.of(SKU, JsonSchemaType.STRING)); - - private static final SourceConnection SOURCE = new SourceConnection() - .withName("my postgres db") - .withWorkspaceId(UUID.randomUUID()) - .withSourceDefinitionId(UUID.randomUUID()) - .withSourceId(UUID.randomUUID()) - .withConfiguration(Jsons.emptyObject()) - .withTombstone(false); - - private static final DestinationConnection DESTINATION = new DestinationConnection() - .withName("my db2 instance") - .withWorkspaceId(UUID.randomUUID()) - .withDestinationDefinitionId(UUID.randomUUID()) - .withDestinationId(UUID.randomUUID()) - .withConfiguration(Jsons.emptyObject()) - .withTombstone(false); - - private static final ConnectorSpecification CONNECTOR_SPECIFICATION = new ConnectorSpecification() - .withDocumentationUrl(Exceptions.toRuntime(() -> new URI("https://google.com"))) - .withChangelogUrl(Exceptions.toRuntime(() -> new URI("https://google.com"))) - .withConnectionSpecification(Jsons.jsonNode(new HashMap<>())); - - private static final ConnectorSpecification CONNECTOR_SPECIFICATION_WITHOUT_DOCS_URL = new ConnectorSpecification() - .withChangelogUrl(Exceptions.toRuntime(() -> new URI("https://google.com"))) - .withConnectionSpecification(Jsons.jsonNode(new HashMap<>())); - - private static final StreamDescriptor STREAM_DESCRIPTOR = new StreamDescriptor().withName("1"); - - private SchedulerHandler schedulerHandler; - private ConfigRepository configRepository; - private SecretsRepositoryWriter secretsRepositoryWriter; - private Job completedJob; - private SynchronousSchedulerClient synchronousSchedulerClient; - private SynchronousResponse jobResponse; - private ConfigurationUpdate configurationUpdate; - private JsonSchemaValidator jsonSchemaValidator; - private JobPersistence jobPersistence; - private EventRunner eventRunner; - private JobConverter jobConverter; - private ConnectionsHandler connectionsHandler; - private EnvVariableFeatureFlags envVariableFeatureFlags; - private WebUrlHelper webUrlHelper; - - @BeforeEach - void setup() { - completedJob = mock(Job.class, RETURNS_DEEP_STUBS); - jobResponse = mock(SynchronousResponse.class, RETURNS_DEEP_STUBS); - final SynchronousJobMetadata synchronousJobMetadata = mock(SynchronousJobMetadata.class); - when(synchronousJobMetadata.getConfigType()) - .thenReturn(ConfigType.SYNC); - when(jobResponse.getMetadata()) - .thenReturn(synchronousJobMetadata); - configurationUpdate = mock(ConfigurationUpdate.class); - jsonSchemaValidator = mock(JsonSchemaValidator.class); - when(completedJob.getStatus()).thenReturn(JobStatus.SUCCEEDED); - when(completedJob.getConfig().getConfigType()).thenReturn(ConfigType.SYNC); - when(completedJob.getScope()).thenReturn("sync:123"); - - synchronousSchedulerClient = mock(SynchronousSchedulerClient.class); - configRepository = mock(ConfigRepository.class); - secretsRepositoryWriter = mock(SecretsRepositoryWriter.class); - jobPersistence = mock(JobPersistence.class); - eventRunner = mock(EventRunner.class); - connectionsHandler = mock(ConnectionsHandler.class); - envVariableFeatureFlags = mock(EnvVariableFeatureFlags.class); - webUrlHelper = mock(WebUrlHelper.class); - - jobConverter = spy(new JobConverter(WorkerEnvironment.DOCKER, LogConfigs.EMPTY)); - - schedulerHandler = new SchedulerHandler( - configRepository, - secretsRepositoryWriter, - synchronousSchedulerClient, - configurationUpdate, - jsonSchemaValidator, - jobPersistence, - eventRunner, - jobConverter, - connectionsHandler, - envVariableFeatureFlags, - webUrlHelper); - } - - @Test - void testCheckSourceConnectionFromSourceId() throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceIdRequestBody request = new SourceIdRequestBody().sourceId(source.getSourceId()); - final Version protocolVersion = new Version(SOURCE_PROTOCOL_VERSION); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createSourceCheckConnectionJob(source, SOURCE_DOCKER_IMAGE, protocolVersion, false)) - .thenReturn((SynchronousResponse) jobResponse); - - schedulerHandler.checkSourceConnectionFromSourceId(request); - - verify(configRepository).getSourceConnection(source.getSourceId()); - verify(synchronousSchedulerClient).createSourceCheckConnectionJob(source, SOURCE_DOCKER_IMAGE, protocolVersion, false); - } - - @Test - void testCheckSourceConnectionFromSourceCreate() throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceConnection source = new SourceConnection() - .withSourceDefinitionId(SOURCE.getSourceDefinitionId()) - .withConfiguration(SOURCE.getConfiguration()); - - final SourceCoreConfig sourceCoreConfig = new SourceCoreConfig() - .sourceDefinitionId(source.getSourceDefinitionId()) - .connectionConfiguration(source.getConfiguration()) - .workspaceId(source.getWorkspaceId()); - - final Version protocolVersion = new Version(SOURCE_PROTOCOL_VERSION); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(secretsRepositoryWriter.statefulSplitEphemeralSecrets( - eq(source.getConfiguration()), - any())).thenReturn(source.getConfiguration()); - when(synchronousSchedulerClient.createSourceCheckConnectionJob(source, SOURCE_DOCKER_IMAGE, protocolVersion, false)) - .thenReturn((SynchronousResponse) jobResponse); - - schedulerHandler.checkSourceConnectionFromSourceCreate(sourceCoreConfig); - - verify(synchronousSchedulerClient).createSourceCheckConnectionJob(source, SOURCE_DOCKER_IMAGE, protocolVersion, false); - } - - @Test - void testCheckSourceConnectionFromUpdate() throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceUpdate sourceUpdate = new SourceUpdate() - .name(source.getName()) - .sourceId(source.getSourceId()) - .connectionConfiguration(source.getConfiguration()); - final StandardSourceDefinition sourceDefinition = new StandardSourceDefinition() - .withDockerRepository(DESTINATION_DOCKER_REPO) - .withDockerImageTag(DESTINATION_DOCKER_TAG) - .withProtocolVersion(DESTINATION_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()) - .withSpec(CONNECTOR_SPECIFICATION); - final Version protocolVersion = new Version(DESTINATION_PROTOCOL_VERSION); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(configurationUpdate.source(source.getSourceId(), source.getName(), sourceUpdate.getConnectionConfiguration())).thenReturn(source); - final SourceConnection submittedSource = new SourceConnection() - .withSourceId(source.getSourceId()) - .withSourceDefinitionId(source.getSourceDefinitionId()) - .withConfiguration(source.getConfiguration()) - .withWorkspaceId(source.getWorkspaceId()); - when(synchronousSchedulerClient.createSourceCheckConnectionJob(submittedSource, DESTINATION_DOCKER_IMAGE, protocolVersion, false)) - .thenReturn((SynchronousResponse) jobResponse); - when(secretsRepositoryWriter.statefulSplitEphemeralSecrets( - eq(source.getConfiguration()), - any())).thenReturn(source.getConfiguration()); - schedulerHandler.checkSourceConnectionFromSourceIdForUpdate(sourceUpdate); - - verify(jsonSchemaValidator).ensure(CONNECTOR_SPECIFICATION.getConnectionSpecification(), source.getConfiguration()); - verify(synchronousSchedulerClient).createSourceCheckConnectionJob(submittedSource, DESTINATION_DOCKER_IMAGE, protocolVersion, false); - } - - @Test - void testGetSourceSpec() throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId = - new SourceDefinitionIdWithWorkspaceId().sourceDefinitionId(UUID.randomUUID()).workspaceId(UUID.randomUUID()); - - final StandardSourceDefinition sourceDefinition = new StandardSourceDefinition() - .withName(NAME) - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withSourceDefinitionId(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId()) - .withSpec(CONNECTOR_SPECIFICATION); - when(configRepository.getStandardSourceDefinition(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - - final SourceDefinitionSpecificationRead response = schedulerHandler.getSourceDefinitionSpecification(sourceDefinitionIdWithWorkspaceId); - - verify(configRepository).getStandardSourceDefinition(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId()); - assertEquals(CONNECTOR_SPECIFICATION.getConnectionSpecification(), response.getConnectionSpecification()); - } - - @Test - void testGetSourceSpecWithoutDocs() throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId = - new SourceDefinitionIdWithWorkspaceId().sourceDefinitionId(UUID.randomUUID()).workspaceId(UUID.randomUUID()); - - final StandardSourceDefinition sourceDefinition = new StandardSourceDefinition() - .withName(NAME) - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withSourceDefinitionId(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId()) - .withSpec(CONNECTOR_SPECIFICATION_WITHOUT_DOCS_URL); - when(configRepository.getStandardSourceDefinition(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - - final SourceDefinitionSpecificationRead response = schedulerHandler.getSourceDefinitionSpecification(sourceDefinitionIdWithWorkspaceId); - - verify(configRepository).getStandardSourceDefinition(sourceDefinitionIdWithWorkspaceId.getSourceDefinitionId()); - assertEquals(CONNECTOR_SPECIFICATION_WITHOUT_DOCS_URL.getConnectionSpecification(), response.getConnectionSpecification()); - } - - @Test - void testGetDestinationSpec() throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId = - new DestinationDefinitionIdWithWorkspaceId().destinationDefinitionId(UUID.randomUUID()).workspaceId(UUID.randomUUID()); - - final StandardDestinationDefinition destinationDefinition = new StandardDestinationDefinition() - .withName(NAME) - .withDockerRepository(DESTINATION_DOCKER_REPO) - .withDockerImageTag(DESTINATION_DOCKER_TAG) - .withDestinationDefinitionId(destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId()) - .withSpec(CONNECTOR_SPECIFICATION); - when(configRepository.getStandardDestinationDefinition(destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - - final DestinationDefinitionSpecificationRead response = schedulerHandler.getDestinationSpecification(destinationDefinitionIdWithWorkspaceId); - - verify(configRepository).getStandardDestinationDefinition(destinationDefinitionIdWithWorkspaceId.getDestinationDefinitionId()); - assertEquals(CONNECTOR_SPECIFICATION.getConnectionSpecification(), response.getConnectionSpecification()); - } - - @Test - void testCheckDestinationConnectionFromDestinationId() throws IOException, JsonValidationException, ConfigNotFoundException { - final DestinationConnection destination = DestinationHelpers.generateDestination(UUID.randomUUID()); - final DestinationIdRequestBody request = new DestinationIdRequestBody().destinationId(destination.getDestinationId()); - - when(configRepository.getStandardDestinationDefinition(destination.getDestinationDefinitionId())) - .thenReturn(new StandardDestinationDefinition() - .withDockerRepository(DESTINATION_DOCKER_REPO) - .withDockerImageTag(DESTINATION_DOCKER_TAG) - .withProtocolVersion(DESTINATION_PROTOCOL_VERSION) - .withDestinationDefinitionId(destination.getDestinationDefinitionId())); - when(configRepository.getDestinationConnection(destination.getDestinationId())).thenReturn(destination); - when(synchronousSchedulerClient.createDestinationCheckConnectionJob(destination, DESTINATION_DOCKER_IMAGE, - new Version(DESTINATION_PROTOCOL_VERSION), false)) - .thenReturn((SynchronousResponse) jobResponse); - - schedulerHandler.checkDestinationConnectionFromDestinationId(request); - - verify(configRepository).getDestinationConnection(destination.getDestinationId()); - verify(synchronousSchedulerClient).createDestinationCheckConnectionJob(destination, DESTINATION_DOCKER_IMAGE, - new Version(DESTINATION_PROTOCOL_VERSION), false); - } - - @Test - void testCheckDestinationConnectionFromDestinationCreate() throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationConnection destination = new DestinationConnection() - .withDestinationDefinitionId(DESTINATION.getDestinationDefinitionId()) - .withConfiguration(DESTINATION.getConfiguration()); - - final DestinationCoreConfig destinationCoreConfig = new DestinationCoreConfig() - .destinationDefinitionId(destination.getDestinationDefinitionId()) - .connectionConfiguration(destination.getConfiguration()); - - when(configRepository.getStandardDestinationDefinition(destination.getDestinationDefinitionId())) - .thenReturn(new StandardDestinationDefinition() - .withDockerRepository(DESTINATION_DOCKER_REPO) - .withDockerImageTag(DESTINATION_DOCKER_TAG) - .withProtocolVersion(DESTINATION_PROTOCOL_VERSION) - .withDestinationDefinitionId(destination.getDestinationDefinitionId())); - - when(synchronousSchedulerClient.createDestinationCheckConnectionJob(destination, DESTINATION_DOCKER_IMAGE, - new Version(DESTINATION_PROTOCOL_VERSION), false)) - .thenReturn((SynchronousResponse) jobResponse); - when(secretsRepositoryWriter.statefulSplitEphemeralSecrets( - eq(destination.getConfiguration()), - any())).thenReturn(destination.getConfiguration()); - schedulerHandler.checkDestinationConnectionFromDestinationCreate(destinationCoreConfig); - - verify(synchronousSchedulerClient).createDestinationCheckConnectionJob(destination, DESTINATION_DOCKER_IMAGE, - new Version(DESTINATION_PROTOCOL_VERSION), false); - } - - @Test - void testCheckDestinationConnectionFromUpdate() throws IOException, JsonValidationException, ConfigNotFoundException { - final DestinationConnection destination = DestinationHelpers.generateDestination(UUID.randomUUID()); - final DestinationUpdate destinationUpdate = new DestinationUpdate() - .name(destination.getName()) - .destinationId(destination.getDestinationId()) - .connectionConfiguration(destination.getConfiguration()); - final StandardDestinationDefinition destinationDefinition = new StandardDestinationDefinition() - .withDockerRepository(DESTINATION_DOCKER_REPO) - .withDockerImageTag(DESTINATION_DOCKER_TAG) - .withProtocolVersion(DESTINATION_PROTOCOL_VERSION) - .withDestinationDefinitionId(destination.getDestinationDefinitionId()) - .withSpec(CONNECTOR_SPECIFICATION); - when(configRepository.getStandardDestinationDefinition(destination.getDestinationDefinitionId())) - .thenReturn(destinationDefinition); - when(configRepository.getDestinationConnection(destination.getDestinationId())).thenReturn(destination); - when(configurationUpdate.destination(destination.getDestinationId(), destination.getName(), destinationUpdate.getConnectionConfiguration())) - .thenReturn(destination); - final DestinationConnection submittedDestination = new DestinationConnection() - .withDestinationId(destination.getDestinationId()) - .withDestinationDefinitionId(destination.getDestinationDefinitionId()) - .withConfiguration(destination.getConfiguration()) - .withWorkspaceId(destination.getWorkspaceId()); - when(synchronousSchedulerClient.createDestinationCheckConnectionJob(submittedDestination, DESTINATION_DOCKER_IMAGE, - new Version(DESTINATION_PROTOCOL_VERSION), false)) - .thenReturn((SynchronousResponse) jobResponse); - when(secretsRepositoryWriter.statefulSplitEphemeralSecrets( - eq(destination.getConfiguration()), - any())).thenReturn(destination.getConfiguration()); - schedulerHandler.checkDestinationConnectionFromDestinationIdForUpdate(destinationUpdate); - - verify(jsonSchemaValidator).ensure(CONNECTOR_SPECIFICATION.getConnectionSpecification(), destination.getConfiguration()); - verify(synchronousSchedulerClient).createDestinationCheckConnectionJob(submittedDestination, DESTINATION_DOCKER_IMAGE, - new Version(DESTINATION_PROTOCOL_VERSION), false); - } - - @Test - void testDiscoverSchemaForSourceFromSourceId() throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceDiscoverSchemaRequestBody request = new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()); - - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SynchronousJobMetadata metadata = mock(SynchronousJobMetadata.class); - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(UUID.randomUUID()); - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(UUID.randomUUID()); - when(configRepository.getActorCatalogById(any())).thenReturn(actorCatalog); - when(discoverResponse.getMetadata()).thenReturn(metadata); - when(metadata.isSucceeded()).thenReturn(true); - - final ConnectionRead connectionRead = new ConnectionRead(); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(configRepository.getActorCatalog(any(), any(), any())).thenReturn(Optional.empty()); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - - assertNotNull(actual.getCatalog()); - assertEquals(actual.getCatalogId(), discoverResponse.getOutput()); - assertNotNull(actual.getJobInfo()); - assertTrue(actual.getJobInfo().getSucceeded()); - verify(configRepository).getSourceConnection(source.getSourceId()); - verify(configRepository).getActorCatalog(eq(request.getSourceId()), eq(SOURCE_DOCKER_TAG), any()); - verify(synchronousSchedulerClient).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false); - } - - @Test - void testDiscoverSchemaForSourceFromSourceIdCachedCatalog() throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceDiscoverSchemaRequestBody request = new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()); - - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SynchronousJobMetadata metadata = mock(SynchronousJobMetadata.class); - final UUID thisCatalogId = UUID.randomUUID(); - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(thisCatalogId); - when(discoverResponse.getMetadata()).thenReturn(metadata); - when(metadata.isSucceeded()).thenReturn(true); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(thisCatalogId); - when(configRepository.getActorCatalog(any(), any(), any())).thenReturn(Optional.of(actorCatalog)); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - - assertNotNull(actual.getCatalog()); - assertNotNull(actual.getJobInfo()); - assertEquals(actual.getCatalogId(), discoverResponse.getOutput()); - assertTrue(actual.getJobInfo().getSucceeded()); - verify(configRepository).getSourceConnection(source.getSourceId()); - verify(configRepository).getActorCatalog(eq(request.getSourceId()), any(), any()); - verify(configRepository, never()).writeActorCatalogFetchEvent(any(), any(), any(), any()); - verify(synchronousSchedulerClient, never()).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, - new Version(SOURCE_PROTOCOL_VERSION), false); - } - - @Test - void testDiscoverSchemaForSourceFromSourceIdDisableCache() throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceDiscoverSchemaRequestBody request = new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).disableCache(true); - - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SynchronousJobMetadata metadata = mock(SynchronousJobMetadata.class); - when(discoverResponse.isSuccess()).thenReturn(true); - final UUID discoveredCatalogId = UUID.randomUUID(); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - when(discoverResponse.getMetadata()).thenReturn(metadata); - when(metadata.isSucceeded()).thenReturn(true); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - - assertNotNull(actual.getCatalog()); - assertNotNull(actual.getJobInfo()); - assertTrue(actual.getJobInfo().getSucceeded()); - verify(configRepository).getSourceConnection(source.getSourceId()); - verify(configRepository).getActorCatalog(eq(request.getSourceId()), any(), any()); - verify(synchronousSchedulerClient).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false); - } - - @Test - void testDiscoverSchemaForSourceFromSourceIdFailed() throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceDiscoverSchemaRequestBody request = new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn((SynchronousResponse) jobResponse); - when(completedJob.getSuccessOutput()).thenReturn(Optional.empty()); - when(completedJob.getStatus()).thenReturn(JobStatus.FAILED); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - - assertNull(actual.getCatalog()); - assertNotNull(actual.getJobInfo()); - assertFalse(actual.getJobInfo().getSucceeded()); - verify(configRepository).getSourceConnection(source.getSourceId()); - verify(synchronousSchedulerClient).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionIdNonBreaking() - throws IOException, JsonValidationException, ConfigNotFoundException, InterruptedException, ApiException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - final StreamTransform streamTransform = new StreamTransform().transformType(TransformTypeEnum.REMOVE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)); - final CatalogDiff catalogDiff = new CatalogDiff().addTransformsItem(streamTransform); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId)).thenReturn(CONNECTION_URL); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).connectionId(connectionId) - .notifySchemaChanges(true); - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(actual.getCatalogDiff(), catalogDiff); - assertEquals(actual.getCatalog(), expectedActorCatalog); - verify(eventRunner).sendSchemaChangeNotification(connectionId, CONNECTION_URL); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionIdNonBreakingDisableConnectionPreferenceNoFeatureFlag() - throws IOException, JsonValidationException, ConfigNotFoundException, InterruptedException, ApiException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - final StreamTransform streamTransform = new StreamTransform().transformType(TransformTypeEnum.REMOVE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)); - final CatalogDiff catalogDiff = new CatalogDiff().addTransformsItem(streamTransform); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - when(envVariableFeatureFlags.autoDetectSchema()).thenReturn(false); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId)).thenReturn(CONNECTION_URL); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).nonBreakingChangesPreference( - NonBreakingChangesPreference.DISABLE).status(ConnectionStatus.ACTIVE).connectionId(connectionId).notifySchemaChanges(true); - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(actual.getCatalogDiff(), catalogDiff); - assertEquals(actual.getCatalog(), expectedActorCatalog); - assertEquals(actual.getConnectionStatus(), ConnectionStatus.ACTIVE); - verify(eventRunner).sendSchemaChangeNotification(connectionId, CONNECTION_URL); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionIdNonBreakingDisableConnectionPreferenceFeatureFlag() - throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - final StreamTransform streamTransform = new StreamTransform().transformType(TransformTypeEnum.REMOVE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)); - final CatalogDiff catalogDiff = new CatalogDiff().addTransformsItem(streamTransform); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - when(envVariableFeatureFlags.autoDetectSchema()).thenReturn(true); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).nonBreakingChangesPreference( - NonBreakingChangesPreference.DISABLE).connectionId(connectionId).notifySchemaChanges(false); - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(actual.getCatalogDiff(), catalogDiff); - assertEquals(actual.getCatalog(), expectedActorCatalog); - assertEquals(actual.getConnectionStatus(), ConnectionStatus.INACTIVE); - verifyNoInteractions(eventRunner); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionIdBreaking() - throws IOException, JsonValidationException, ConfigNotFoundException, InterruptedException, ApiException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - final StreamTransform streamTransform = new StreamTransform().transformType(TransformTypeEnum.UPDATE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)).addUpdateStreamItem(new FieldTransform().transformType( - FieldTransform.TransformTypeEnum.REMOVE_FIELD).breaking(true)); - final CatalogDiff catalogDiff = new CatalogDiff().addTransformsItem(streamTransform); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId)).thenReturn(CONNECTION_URL); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).status(ConnectionStatus.ACTIVE) - .connectionId(connectionId) - .notifySchemaChanges(true); - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - final ConnectionUpdate expectedConnectionUpdate = - new ConnectionUpdate().connectionId(connectionId).breakingChange(true).status(ConnectionStatus.ACTIVE); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(actual.getCatalogDiff(), catalogDiff); - assertEquals(actual.getCatalog(), expectedActorCatalog); - assertEquals(actual.getConnectionStatus(), ConnectionStatus.ACTIVE); - verify(connectionsHandler).updateConnection(expectedConnectionUpdate); - verify(eventRunner).sendSchemaChangeNotification(connectionId, CONNECTION_URL); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionIdBreakingFeatureFlagOn() - throws IOException, JsonValidationException, ConfigNotFoundException, InterruptedException, ApiException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - final StreamTransform streamTransform = new StreamTransform().transformType(TransformTypeEnum.UPDATE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)).addUpdateStreamItem(new FieldTransform().transformType( - FieldTransform.TransformTypeEnum.REMOVE_FIELD).breaking(true)); - final CatalogDiff catalogDiff = new CatalogDiff().addTransformsItem(streamTransform); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - when(envVariableFeatureFlags.autoDetectSchema()).thenReturn(true); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId)).thenReturn(CONNECTION_URL); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).connectionId(connectionId) - .notifySchemaChanges(true); - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - final ConnectionUpdate expectedConnectionUpdate = - new ConnectionUpdate().connectionId(connectionId).breakingChange(true).status(ConnectionStatus.INACTIVE); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(actual.getCatalogDiff(), catalogDiff); - assertEquals(actual.getCatalog(), expectedActorCatalog); - assertEquals(actual.getConnectionStatus(), ConnectionStatus.INACTIVE); - verify(connectionsHandler).updateConnection(expectedConnectionUpdate); - verify(eventRunner).sendSchemaChangeNotification(connectionId, CONNECTION_URL); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionIdNonBreakingDisableConnectionPreferenceFeatureFlagNoDiff() - throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - final CatalogDiff catalogDiff = new CatalogDiff(); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - when(envVariableFeatureFlags.autoDetectSchema()).thenReturn(true); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).nonBreakingChangesPreference( - NonBreakingChangesPreference.DISABLE).status(ConnectionStatus.INACTIVE).connectionId(connectionId).notifySchemaChanges(false); - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(actual.getCatalogDiff(), catalogDiff); - assertEquals(actual.getCatalog(), expectedActorCatalog); - assertEquals(actual.getConnectionStatus(), ConnectionStatus.INACTIVE); - // notification preferences are turned on, but there is no schema diff detected - verifyNoInteractions(eventRunner); - } - - @Test - void testDiscoverSchemaForSourceMultipleConnectionsFeatureFlagOn() - throws IOException, JsonValidationException, ConfigNotFoundException, InterruptedException, ApiException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final UUID connectionId = UUID.randomUUID(); - final UUID connectionId2 = UUID.randomUUID(); - final UUID connectionId3 = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SourceDiscoverSchemaRequestBody request = - new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()).connectionId(connectionId).disableCache(true).notifySchemaChange(true); - - // 3 connections use the same source. 2 will generate catalog diffs that are non-breaking, 1 will - // generate a breaking catalog diff - final StreamTransform nonBreakingStreamTransform = new StreamTransform().transformType(TransformTypeEnum.UPDATE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)).addUpdateStreamItem(new FieldTransform().transformType( - FieldTransform.TransformTypeEnum.REMOVE_FIELD).breaking(false)); - final StreamTransform breakingStreamTransform = new StreamTransform().transformType(TransformTypeEnum.UPDATE_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name(DOGS)).addUpdateStreamItem(new FieldTransform().transformType( - FieldTransform.TransformTypeEnum.REMOVE_FIELD).breaking(true)); - - final CatalogDiff catalogDiff1 = new CatalogDiff().addTransformsItem(nonBreakingStreamTransform); - final CatalogDiff catalogDiff2 = new CatalogDiff().addTransformsItem(nonBreakingStreamTransform); - final CatalogDiff catalogDiff3 = new CatalogDiff().addTransformsItem(breakingStreamTransform); - final StandardSourceDefinition sourceDef = new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId()); - - when(envVariableFeatureFlags.autoDetectSchema()).thenReturn(true); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(sourceDef); - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId)).thenReturn(CONNECTION_URL); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId2)).thenReturn(CONNECTION_URL); - when(webUrlHelper.getConnectionUrl(source.getWorkspaceId(), connectionId3)).thenReturn(CONNECTION_URL); - - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(discoveredCatalogId); - - final AirbyteCatalog airbyteCatalogCurrent = new AirbyteCatalog().withStreams(Lists.newArrayList( - CatalogHelpers.createAirbyteStream(SHOES, Field.of(SKU, JsonSchemaType.STRING)), - CatalogHelpers.createAirbyteStream(DOGS, Field.of(NAME, JsonSchemaType.STRING)))); - - final ConnectionRead connectionRead = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).nonBreakingChangesPreference( - NonBreakingChangesPreference.IGNORE).status(ConnectionStatus.ACTIVE).connectionId(connectionId).notifySchemaChanges(true); - - final ConnectionRead connectionRead2 = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).nonBreakingChangesPreference( - NonBreakingChangesPreference.IGNORE).status(ConnectionStatus.ACTIVE).connectionId(connectionId2).notifySchemaChanges(true); - - final ConnectionRead connectionRead3 = - new ConnectionRead().syncCatalog(CatalogConverter.toApi(airbyteCatalogCurrent, sourceDef)).nonBreakingChangesPreference( - NonBreakingChangesPreference.DISABLE).status(ConnectionStatus.ACTIVE).connectionId(connectionId3).notifySchemaChanges(false); - - when(connectionsHandler.getConnection(request.getConnectionId())).thenReturn(connectionRead, connectionRead2, connectionRead3); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff1, catalogDiff2, catalogDiff3); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(List.of(connectionRead, connectionRead2, connectionRead3)); - when(connectionsHandler.listConnectionsForSource(source.getSourceId(), false)).thenReturn(connectionReadList); - - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(discoveredCatalogId); - when(configRepository.getActorCatalogById(discoveredCatalogId)).thenReturn(actorCatalog); - - final AirbyteCatalog persistenceCatalog = Jsons.object(actorCatalog.getCatalog(), - io.airbyte.protocol.models.AirbyteCatalog.class); - final io.airbyte.api.model.generated.AirbyteCatalog expectedActorCatalog = CatalogConverter.toApi(persistenceCatalog, sourceDef); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - assertEquals(catalogDiff1, actual.getCatalogDiff()); - assertEquals(expectedActorCatalog, actual.getCatalog()); - assertEquals(ConnectionStatus.ACTIVE, actual.getConnectionStatus()); - - final ArgumentCaptor expectedArgumentCaptor = ArgumentCaptor.forClass(ConnectionUpdate.class); - verify(connectionsHandler, times(3)).updateConnection(expectedArgumentCaptor.capture()); - final List connectionUpdateValues = expectedArgumentCaptor.getAllValues(); - assertEquals(ConnectionStatus.ACTIVE, connectionUpdateValues.get(0).getStatus()); - assertEquals(ConnectionStatus.ACTIVE, connectionUpdateValues.get(1).getStatus()); - assertEquals(ConnectionStatus.INACTIVE, connectionUpdateValues.get(2).getStatus()); - verify(eventRunner).sendSchemaChangeNotification(connectionId, CONNECTION_URL); - verify(eventRunner).sendSchemaChangeNotification(connectionId2, CONNECTION_URL); - verify(eventRunner, times(0)).sendSchemaChangeNotification(connectionId3, CONNECTION_URL); - } - - @Test - void testDiscoverSchemaFromSourceIdWithConnectionUpdateNonSuccessResponse() throws IOException, JsonValidationException, ConfigNotFoundException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final SourceDiscoverSchemaRequestBody request = new SourceDiscoverSchemaRequestBody().sourceId(source.getSourceId()) - .connectionId(UUID.randomUUID()).notifySchemaChange(true); - - // Mock the source definition. - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - // Mock the source itself. - when(configRepository.getSourceConnection(source.getSourceId())).thenReturn(source); - // Mock the Discover job results. - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SynchronousJobMetadata metadata = mock(SynchronousJobMetadata.class); - when(discoverResponse.isSuccess()).thenReturn(false); - when(discoverResponse.getMetadata()).thenReturn(metadata); - when(metadata.isSucceeded()).thenReturn(false); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceId(request); - - assertNull(actual.getCatalog()); - assertNotNull(actual.getJobInfo()); - assertFalse(actual.getJobInfo().getSucceeded()); - verify(synchronousSchedulerClient).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false); - } - - @Test - void testDiscoverSchemaForSourceFromSourceCreate() throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceConnection source = new SourceConnection() - .withSourceDefinitionId(SOURCE.getSourceDefinitionId()) - .withConfiguration(SOURCE.getConfiguration()); - - final SynchronousResponse discoverResponse = (SynchronousResponse) jobResponse; - final SynchronousJobMetadata metadata = mock(SynchronousJobMetadata.class); - when(discoverResponse.isSuccess()).thenReturn(true); - when(discoverResponse.getOutput()).thenReturn(UUID.randomUUID()); - when(discoverResponse.getMetadata()).thenReturn(metadata); - when(metadata.isSucceeded()).thenReturn(true); - - final SourceCoreConfig sourceCoreConfig = new SourceCoreConfig() - .sourceDefinitionId(source.getSourceDefinitionId()) - .connectionConfiguration(source.getConfiguration()) - .workspaceId(source.getWorkspaceId()); - final ActorCatalog actorCatalog = new ActorCatalog() - .withCatalog(Jsons.jsonNode(airbyteCatalog)) - .withCatalogHash("") - .withId(UUID.randomUUID()); - when(configRepository.getActorCatalogById(any())).thenReturn(actorCatalog); - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn(discoverResponse); - when(secretsRepositoryWriter.statefulSplitEphemeralSecrets( - eq(source.getConfiguration()), - any())).thenReturn(source.getConfiguration()); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceCreate(sourceCoreConfig); - - assertNotNull(actual.getCatalog()); - assertNotNull(actual.getJobInfo()); - assertEquals(actual.getCatalogId(), discoverResponse.getOutput()); - assertTrue(actual.getJobInfo().getSucceeded()); - verify(synchronousSchedulerClient).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false); - } - - @Test - void testDiscoverSchemaForSourceFromSourceCreateFailed() throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceConnection source = new SourceConnection() - .withSourceDefinitionId(SOURCE.getSourceDefinitionId()) - .withConfiguration(SOURCE.getConfiguration()); - - final SourceCoreConfig sourceCoreConfig = new SourceCoreConfig() - .sourceDefinitionId(source.getSourceDefinitionId()) - .connectionConfiguration(source.getConfiguration()) - .workspaceId(source.getWorkspaceId()); - - when(configRepository.getStandardSourceDefinition(source.getSourceDefinitionId())) - .thenReturn(new StandardSourceDefinition() - .withDockerRepository(SOURCE_DOCKER_REPO) - .withDockerImageTag(SOURCE_DOCKER_TAG) - .withProtocolVersion(SOURCE_PROTOCOL_VERSION) - .withSourceDefinitionId(source.getSourceDefinitionId())); - when(synchronousSchedulerClient.createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false)) - .thenReturn((SynchronousResponse) jobResponse); - when(secretsRepositoryWriter.statefulSplitEphemeralSecrets( - eq(source.getConfiguration()), - any())).thenReturn(source.getConfiguration()); - when(completedJob.getSuccessOutput()).thenReturn(Optional.empty()); - when(completedJob.getStatus()).thenReturn(JobStatus.FAILED); - - final SourceDiscoverSchemaRead actual = schedulerHandler.discoverSchemaForSourceFromSourceCreate(sourceCoreConfig); - - assertNull(actual.getCatalog()); - assertNotNull(actual.getJobInfo()); - assertFalse(actual.getJobInfo().getSucceeded()); - verify(synchronousSchedulerClient).createDiscoverSchemaJob(source, SOURCE_DOCKER_IMAGE, SOURCE_DOCKER_TAG, new Version(SOURCE_PROTOCOL_VERSION), - false); - } - - @Test - void testEnumConversion() { - assertTrue(Enums.isCompatible(StandardCheckConnectionOutput.Status.class, CheckConnectionRead.StatusEnum.class)); - assertTrue(Enums.isCompatible(JobStatus.class, io.airbyte.api.model.generated.JobStatus.class)); - } - - @Test - void testSyncConnection() throws IOException, JsonValidationException, ConfigNotFoundException { - final UUID connectionId = UUID.randomUUID(); - - final long jobId = 123L; - final ManualOperationResult manualOperationResult = ManualOperationResult - .builder() - .failingReason(Optional.empty()) - .jobId(Optional.of(jobId)) - .build(); - - when(eventRunner.startNewManualSync(connectionId)) - .thenReturn(manualOperationResult); - - doReturn(new JobInfoRead()) - .when(jobConverter).getJobInfoRead(any()); - - schedulerHandler.syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - verify(eventRunner).startNewManualSync(connectionId); - } - - @Test - void testSyncConnectionFailWithOtherSyncRunning() throws IOException { - final UUID connectionId = UUID.randomUUID(); - - final ManualOperationResult manualOperationResult = ManualOperationResult - .builder() - .failingReason(Optional.of("another sync running")) - .jobId(Optional.empty()) - .errorCode(Optional.of(ErrorCode.WORKFLOW_RUNNING)) - .build(); - - when(eventRunner.startNewManualSync(connectionId)) - .thenReturn(manualOperationResult); - - assertThrows(ValueConflictKnownException.class, - () -> schedulerHandler.syncConnection(new ConnectionIdRequestBody().connectionId(connectionId))); - - } - - @Test - void testResetConnection() throws IOException, JsonValidationException, ConfigNotFoundException { - final UUID connectionId = UUID.randomUUID(); - - final long jobId = 123L; - final ManualOperationResult manualOperationResult = ManualOperationResult - .builder() - .failingReason(Optional.empty()) - .jobId(Optional.of(jobId)) - .build(); - - final List streamDescriptors = List.of(STREAM_DESCRIPTOR); - when(configRepository.getAllStreamsForConnection(connectionId)) - .thenReturn(streamDescriptors); - - when(eventRunner.resetConnection(connectionId, streamDescriptors, false)) - .thenReturn(manualOperationResult); - - doReturn(new JobInfoRead()) - .when(jobConverter).getJobInfoRead(any()); - - schedulerHandler.resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - verify(eventRunner).resetConnection(connectionId, streamDescriptors, false); - } - - @Test - void testCancelJob() throws IOException { - final UUID connectionId = UUID.randomUUID(); - final long jobId = 123L; - final Job job = mock(Job.class); - when(job.getScope()).thenReturn(connectionId.toString()); - when(jobPersistence.getJob(jobId)).thenReturn(job); - - final ManualOperationResult manualOperationResult = ManualOperationResult - .builder() - .failingReason(Optional.empty()) - .jobId(Optional.of(jobId)) - .build(); - - when(eventRunner.startNewCancellation(connectionId)) - .thenReturn(manualOperationResult); - - doReturn(new JobInfoRead()) - .when(jobConverter).getJobInfoRead(any()); - - schedulerHandler.cancelJob(new JobIdRequestBody().id(jobId)); - - verify(eventRunner).startNewCancellation(connectionId); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandlerTest.java deleted file mode 100644 index c4a98f1e85f82..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/SourceDefinitionsHandlerTest.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.CustomSourceDefinitionCreate; -import io.airbyte.api.model.generated.PrivateSourceDefinitionRead; -import io.airbyte.api.model.generated.PrivateSourceDefinitionReadList; -import io.airbyte.api.model.generated.ReleaseStage; -import io.airbyte.api.model.generated.SourceDefinitionCreate; -import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.SourceDefinitionRead; -import io.airbyte.api.model.generated.SourceDefinitionReadList; -import io.airbyte.api.model.generated.SourceDefinitionUpdate; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceReadList; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.commons.server.errors.UnsupportedProtocolVersionException; -import io.airbyte.commons.server.scheduler.SynchronousJobMetadata; -import io.airbyte.commons.server.scheduler.SynchronousResponse; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorDefinitionResourceRequirements; -import io.airbyte.config.ActorType; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.ResourceRequirements; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.protocol.models.ConnectorSpecification; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.time.LocalDate; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; -import java.util.function.Supplier; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -class SourceDefinitionsHandlerTest { - - private static final String TODAY_DATE_STRING = LocalDate.now().toString(); - private static final String DEFAULT_PROTOCOL_VERSION = "0.2.0"; - - private ConfigRepository configRepository; - private StandardSourceDefinition sourceDefinition; - private SourceDefinitionsHandler sourceDefinitionsHandler; - private Supplier uuidSupplier; - private SynchronousSchedulerClient schedulerSynchronousClient; - private AirbyteGithubStore githubStore; - private SourceHandler sourceHandler; - private UUID workspaceId; - private AirbyteProtocolVersionRange protocolVersionRange; - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() { - configRepository = mock(ConfigRepository.class); - uuidSupplier = mock(Supplier.class); - schedulerSynchronousClient = spy(SynchronousSchedulerClient.class); - githubStore = mock(AirbyteGithubStore.class); - sourceHandler = mock(SourceHandler.class); - workspaceId = UUID.randomUUID(); - - sourceDefinition = generateSourceDefinition(); - - protocolVersionRange = new AirbyteProtocolVersionRange(new Version("0.0.0"), new Version("0.3.0")); - - sourceDefinitionsHandler = new SourceDefinitionsHandler(configRepository, uuidSupplier, schedulerSynchronousClient, githubStore, sourceHandler, - protocolVersionRange); - } - - private StandardSourceDefinition generateSourceDefinition() { - final UUID sourceDefinitionId = UUID.randomUUID(); - final ConnectorSpecification spec = new ConnectorSpecification().withConnectionSpecification( - Jsons.jsonNode(ImmutableMap.of("foo", "bar"))); - - return new StandardSourceDefinition() - .withSourceDefinitionId(sourceDefinitionId) - .withName("presto") - .withDocumentationUrl("https://netflix.com") - .withDockerRepository("dockerstuff") - .withDockerImageTag("12.3") - .withIcon("rss.svg") - .withSpec(spec) - .withTombstone(false) - .withReleaseStage(StandardSourceDefinition.ReleaseStage.ALPHA) - .withReleaseDate(TODAY_DATE_STRING) - .withResourceRequirements(new ActorDefinitionResourceRequirements().withDefault(new ResourceRequirements().withCpuRequest("2"))); - - } - - @Test - @DisplayName("listSourceDefinition should return the right list") - void testListSourceDefinitions() throws JsonValidationException, IOException, URISyntaxException { - final StandardSourceDefinition sourceDefinition2 = generateSourceDefinition(); - - when(configRepository.listStandardSourceDefinitions(false)).thenReturn(Lists.newArrayList(sourceDefinition, sourceDefinition2)); - - final SourceDefinitionRead expectedSourceDefinitionRead1 = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionRead expectedSourceDefinitionRead2 = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition2.getSourceDefinitionId()) - .name(sourceDefinition2.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition2.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionReadList actualSourceDefinitionReadList = sourceDefinitionsHandler.listSourceDefinitions(); - - assertEquals( - Lists.newArrayList(expectedSourceDefinitionRead1, expectedSourceDefinitionRead2), - actualSourceDefinitionReadList.getSourceDefinitions()); - } - - @Test - @DisplayName("listSourceDefinitionsForWorkspace should return the right list") - void testListSourceDefinitionsForWorkspace() throws IOException, URISyntaxException { - final StandardSourceDefinition sourceDefinition2 = generateSourceDefinition(); - - when(configRepository.listPublicSourceDefinitions(false)).thenReturn(Lists.newArrayList(sourceDefinition)); - when(configRepository.listGrantedSourceDefinitions(workspaceId, false)).thenReturn(Lists.newArrayList(sourceDefinition2)); - - final SourceDefinitionRead expectedSourceDefinitionRead1 = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionRead expectedSourceDefinitionRead2 = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition2.getSourceDefinitionId()) - .name(sourceDefinition2.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition2.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionReadList actualSourceDefinitionReadList = - sourceDefinitionsHandler.listSourceDefinitionsForWorkspace(new WorkspaceIdRequestBody().workspaceId(workspaceId)); - - assertEquals( - Lists.newArrayList(expectedSourceDefinitionRead1, expectedSourceDefinitionRead2), - actualSourceDefinitionReadList.getSourceDefinitions()); - } - - @Test - @DisplayName("listPrivateSourceDefinitions should return the right list") - void testListPrivateSourceDefinitions() throws IOException, URISyntaxException { - final StandardSourceDefinition sourceDefinition2 = generateSourceDefinition(); - - when(configRepository.listGrantableSourceDefinitions(workspaceId, false)).thenReturn( - Lists.newArrayList( - Map.entry(sourceDefinition, false), - Map.entry(sourceDefinition2, true))); - - final SourceDefinitionRead expectedSourceDefinitionRead1 = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionRead expectedSourceDefinitionRead2 = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition2.getSourceDefinitionId()) - .name(sourceDefinition2.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition2.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final PrivateSourceDefinitionRead expectedSourceDefinitionOptInRead1 = - new PrivateSourceDefinitionRead().sourceDefinition(expectedSourceDefinitionRead1).granted(false); - - final PrivateSourceDefinitionRead expectedSourceDefinitionOptInRead2 = - new PrivateSourceDefinitionRead().sourceDefinition(expectedSourceDefinitionRead2).granted(true); - - final PrivateSourceDefinitionReadList actualSourceDefinitionOptInReadList = sourceDefinitionsHandler.listPrivateSourceDefinitions( - new WorkspaceIdRequestBody().workspaceId(workspaceId)); - - assertEquals( - Lists.newArrayList(expectedSourceDefinitionOptInRead1, expectedSourceDefinitionOptInRead2), - actualSourceDefinitionOptInReadList.getSourceDefinitions()); - } - - @Test - @DisplayName("getSourceDefinition should return the right source") - void testGetSourceDefinition() throws JsonValidationException, ConfigNotFoundException, IOException, URISyntaxException { - when(configRepository.getStandardSourceDefinition(sourceDefinition.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - - final SourceDefinitionRead expectedSourceDefinitionRead = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody = - new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceDefinition.getSourceDefinitionId()); - - final SourceDefinitionRead actualSourceDefinitionRead = sourceDefinitionsHandler.getSourceDefinition(sourceDefinitionIdRequestBody); - - assertEquals(expectedSourceDefinitionRead, actualSourceDefinitionRead); - } - - @Test - @DisplayName("getSourceDefinitionForWorkspace should throw an exception for a missing grant") - void testGetDefinitionWithoutGrantForWorkspace() throws IOException { - when(configRepository.workspaceCanUseDefinition(sourceDefinition.getSourceDefinitionId(), workspaceId)) - .thenReturn(false); - - final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId = new SourceDefinitionIdWithWorkspaceId() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .workspaceId(workspaceId); - - assertThrows(IdNotFoundKnownException.class, () -> sourceDefinitionsHandler.getSourceDefinitionForWorkspace(sourceDefinitionIdWithWorkspaceId)); - } - - @Test - @DisplayName("getSourceDefinitionForWorkspace should return the source if the grant exists") - void testGetDefinitionWithGrantForWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException, URISyntaxException { - when(configRepository.workspaceCanUseDefinition(sourceDefinition.getSourceDefinitionId(), workspaceId)) - .thenReturn(true); - when(configRepository.getStandardSourceDefinition(sourceDefinition.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - - final SourceDefinitionRead expectedSourceDefinitionRead = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId = new SourceDefinitionIdWithWorkspaceId() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .workspaceId(workspaceId); - - final SourceDefinitionRead actualSourceDefinitionRead = sourceDefinitionsHandler - .getSourceDefinitionForWorkspace(sourceDefinitionIdWithWorkspaceId); - - assertEquals(expectedSourceDefinitionRead, actualSourceDefinitionRead); - } - - @Test - @DisplayName("createSourceDefinition should not create a sourceDefinition with an unsupported protocol version") - void testCreateSourceDefinitionWithInvalidProtocol() throws URISyntaxException, IOException, JsonValidationException { - final String invalidProtocol = "131.1.2"; - final StandardSourceDefinition sourceDefinition = generateSourceDefinition(); - sourceDefinition.getSpec().setProtocolVersion(invalidProtocol); - final String imageName = sourceDefinition.getDockerRepository() + ":" + sourceDefinition.getDockerImageTag(); - - when(uuidSupplier.get()).thenReturn(sourceDefinition.getSourceDefinitionId()); - when(schedulerSynchronousClient.createGetSpecJob(imageName, true)).thenReturn(new SynchronousResponse<>( - sourceDefinition.getSpec(), - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final SourceDefinitionCreate create = new SourceDefinitionCreate() - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(sourceDefinition.getIcon()) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - final CustomSourceDefinitionCreate customCreate = new CustomSourceDefinitionCreate() - .sourceDefinition(create) - .workspaceId(workspaceId); - assertThrows(UnsupportedProtocolVersionException.class, () -> sourceDefinitionsHandler.createCustomSourceDefinition(customCreate)); - - verify(schedulerSynchronousClient).createGetSpecJob(imageName, true); - verify(configRepository, never()) - .writeStandardSourceDefinition( - sourceDefinition - .withReleaseDate(null) - .withReleaseStage(StandardSourceDefinition.ReleaseStage.CUSTOM) - .withProtocolVersion(DEFAULT_PROTOCOL_VERSION)); - } - - @Test - @DisplayName("createCustomSourceDefinition should correctly create a sourceDefinition") - void testCreateCustomSourceDefinition() throws URISyntaxException, IOException, JsonValidationException { - final StandardSourceDefinition sourceDefinition = generateSourceDefinition(); - final String imageName = sourceDefinition.getDockerRepository() + ":" + sourceDefinition.getDockerImageTag(); - - when(uuidSupplier.get()).thenReturn(sourceDefinition.getSourceDefinitionId()); - when(schedulerSynchronousClient.createGetSpecJob(imageName, true)).thenReturn(new SynchronousResponse<>( - sourceDefinition.getSpec(), - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final SourceDefinitionCreate create = new SourceDefinitionCreate() - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(sourceDefinition.getIcon()) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final CustomSourceDefinitionCreate customCreate = new CustomSourceDefinitionCreate() - .sourceDefinition(create) - .workspaceId(workspaceId); - - final SourceDefinitionRead expectedRead = new SourceDefinitionRead() - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .protocolVersion(DEFAULT_PROTOCOL_VERSION) - .releaseStage(ReleaseStage.CUSTOM) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final SourceDefinitionRead actualRead = sourceDefinitionsHandler.createCustomSourceDefinition(customCreate); - - assertEquals(expectedRead, actualRead); - verify(schedulerSynchronousClient).createGetSpecJob(imageName, true); - verify(configRepository).writeCustomSourceDefinition( - sourceDefinition - .withReleaseDate(null) - .withReleaseStage(StandardSourceDefinition.ReleaseStage.CUSTOM) - .withProtocolVersion(DEFAULT_PROTOCOL_VERSION) - .withCustom(true), - workspaceId); - } - - @Test - @DisplayName("createCustomSourceDefinition should not create a sourceDefinition with unspported protocol version") - void testCreateCustomSourceDefinitionWithInvalidProtocol() throws URISyntaxException, IOException, JsonValidationException { - final String invalidVersion = "130.0.0"; - final StandardSourceDefinition sourceDefinition = generateSourceDefinition(); - sourceDefinition.getSpec().setProtocolVersion(invalidVersion); - final String imageName = sourceDefinition.getDockerRepository() + ":" + sourceDefinition.getDockerImageTag(); - - when(uuidSupplier.get()).thenReturn(sourceDefinition.getSourceDefinitionId()); - when(schedulerSynchronousClient.createGetSpecJob(imageName, true)).thenReturn(new SynchronousResponse<>( - sourceDefinition.getSpec(), - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final SourceDefinitionCreate create = new SourceDefinitionCreate() - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(sourceDefinition.getIcon()) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final CustomSourceDefinitionCreate customCreate = new CustomSourceDefinitionCreate() - .sourceDefinition(create) - .workspaceId(workspaceId); - - assertThrows(UnsupportedProtocolVersionException.class, () -> sourceDefinitionsHandler.createCustomSourceDefinition(customCreate)); - - verify(schedulerSynchronousClient).createGetSpecJob(imageName, true); - verify(configRepository, never()).writeCustomSourceDefinition( - sourceDefinition - .withReleaseDate(null) - .withReleaseStage(StandardSourceDefinition.ReleaseStage.CUSTOM) - .withProtocolVersion(invalidVersion) - .withCustom(true), - workspaceId); - } - - @Test - @DisplayName("updateSourceDefinition should correctly update a sourceDefinition") - void testUpdateSourceDefinition() throws ConfigNotFoundException, IOException, JsonValidationException, URISyntaxException { - when(configRepository.getStandardSourceDefinition(sourceDefinition.getSourceDefinitionId())).thenReturn(sourceDefinition); - final String newDockerImageTag = "averydifferenttag"; - final String newProtocolVersion = "0.2.1"; - final SourceDefinitionRead sourceDefinition = sourceDefinitionsHandler - .getSourceDefinition(new SourceDefinitionIdRequestBody().sourceDefinitionId(this.sourceDefinition.getSourceDefinitionId())); - final String currentTag = sourceDefinition.getDockerImageTag(); - assertNotEquals(newDockerImageTag, currentTag); - - final String newImageName = this.sourceDefinition.getDockerRepository() + ":" + newDockerImageTag; - final ConnectorSpecification newSpec = new ConnectorSpecification() - .withConnectionSpecification(Jsons.jsonNode(ImmutableMap.of("foo2", "bar2"))) - .withProtocolVersion(newProtocolVersion); - when(schedulerSynchronousClient.createGetSpecJob(newImageName, false)).thenReturn(new SynchronousResponse<>( - newSpec, - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final StandardSourceDefinition updatedSource = Jsons.clone(this.sourceDefinition) - .withDockerImageTag(newDockerImageTag).withSpec(newSpec).withProtocolVersion(newProtocolVersion); - - final SourceDefinitionRead sourceDefinitionRead = sourceDefinitionsHandler - .updateSourceDefinition( - new SourceDefinitionUpdate().sourceDefinitionId(this.sourceDefinition.getSourceDefinitionId()).dockerImageTag(newDockerImageTag)); - - assertEquals(newDockerImageTag, sourceDefinitionRead.getDockerImageTag()); - verify(schedulerSynchronousClient).createGetSpecJob(newImageName, false); - verify(configRepository).writeStandardSourceDefinition(updatedSource); - - verify(configRepository).clearUnsupportedProtocolVersionFlag(updatedSource.getSourceDefinitionId(), ActorType.SOURCE, protocolVersionRange); - } - - @Test - @DisplayName("updateSourceDefinition should not update a sourceDefinition with an invalid protocol version") - void testUpdateSourceDefinitionWithInvalidProtocol() throws ConfigNotFoundException, IOException, JsonValidationException, URISyntaxException { - when(configRepository.getStandardSourceDefinition(sourceDefinition.getSourceDefinitionId())).thenReturn(sourceDefinition); - final String newDockerImageTag = "averydifferenttag"; - final String newProtocolVersion = "132.2.1"; - final SourceDefinitionRead sourceDefinition = sourceDefinitionsHandler - .getSourceDefinition(new SourceDefinitionIdRequestBody().sourceDefinitionId(this.sourceDefinition.getSourceDefinitionId())); - final String currentTag = sourceDefinition.getDockerImageTag(); - assertNotEquals(newDockerImageTag, currentTag); - - final String newImageName = this.sourceDefinition.getDockerRepository() + ":" + newDockerImageTag; - final ConnectorSpecification newSpec = new ConnectorSpecification() - .withConnectionSpecification(Jsons.jsonNode(ImmutableMap.of("foo2", "bar2"))) - .withProtocolVersion(newProtocolVersion); - when(schedulerSynchronousClient.createGetSpecJob(newImageName, false)).thenReturn(new SynchronousResponse<>( - newSpec, - SynchronousJobMetadata.mock(ConfigType.GET_SPEC))); - - final StandardSourceDefinition updatedSource = Jsons.clone(this.sourceDefinition) - .withDockerImageTag(newDockerImageTag).withSpec(newSpec).withProtocolVersion(newProtocolVersion); - - assertThrows(UnsupportedProtocolVersionException.class, () -> sourceDefinitionsHandler - .updateSourceDefinition( - new SourceDefinitionUpdate().sourceDefinitionId(this.sourceDefinition.getSourceDefinitionId()).dockerImageTag(newDockerImageTag))); - - verify(schedulerSynchronousClient).createGetSpecJob(newImageName, false); - verify(configRepository, never()).writeStandardSourceDefinition(updatedSource); - } - - @Test - @DisplayName("deleteSourceDefinition should correctly delete a sourceDefinition") - void testDeleteSourceDefinition() throws ConfigNotFoundException, IOException, JsonValidationException { - final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody = - new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceDefinition.getSourceDefinitionId()); - final StandardSourceDefinition updatedSourceDefinition = Jsons.clone(this.sourceDefinition).withTombstone(true); - final SourceRead source = new SourceRead(); - - when(configRepository.getStandardSourceDefinition(sourceDefinition.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - when(sourceHandler.listSourcesForSourceDefinition(sourceDefinitionIdRequestBody)) - .thenReturn(new SourceReadList().sources(Collections.singletonList(source))); - - assertFalse(sourceDefinition.getTombstone()); - - sourceDefinitionsHandler.deleteSourceDefinition(sourceDefinitionIdRequestBody); - - verify(sourceHandler).deleteSource(source); - verify(configRepository).writeStandardSourceDefinition(updatedSourceDefinition); - } - - @Test - @DisplayName("grantSourceDefinitionToWorkspace should correctly create a workspace grant") - void testGrantSourceDefinitionToWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException, URISyntaxException { - when(configRepository.getStandardSourceDefinition(sourceDefinition.getSourceDefinitionId())) - .thenReturn(sourceDefinition); - - final SourceDefinitionRead expectedSourceDefinitionRead = new SourceDefinitionRead() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .name(sourceDefinition.getName()) - .dockerRepository(sourceDefinition.getDockerRepository()) - .dockerImageTag(sourceDefinition.getDockerImageTag()) - .documentationUrl(new URI(sourceDefinition.getDocumentationUrl())) - .icon(SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon())) - .releaseStage(ReleaseStage.fromValue(sourceDefinition.getReleaseStage().value())) - .releaseDate(LocalDate.parse(sourceDefinition.getReleaseDate())) - .resourceRequirements(new io.airbyte.api.model.generated.ActorDefinitionResourceRequirements() - ._default(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuRequest(sourceDefinition.getResourceRequirements().getDefault().getCpuRequest())) - .jobSpecific(Collections.emptyList())); - - final PrivateSourceDefinitionRead expectedPrivateSourceDefinitionRead = - new PrivateSourceDefinitionRead().sourceDefinition(expectedSourceDefinitionRead).granted(true); - - final PrivateSourceDefinitionRead actualPrivateSourceDefinitionRead = - sourceDefinitionsHandler.grantSourceDefinitionToWorkspace( - new SourceDefinitionIdWithWorkspaceId() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .workspaceId(workspaceId)); - - assertEquals(expectedPrivateSourceDefinitionRead, actualPrivateSourceDefinitionRead); - verify(configRepository).writeActorDefinitionWorkspaceGrant( - sourceDefinition.getSourceDefinitionId(), - workspaceId); - } - - @Test - @DisplayName("revokeSourceDefinitionFromWorkspace should correctly delete a workspace grant") - void testRevokeSourceDefinitionFromWorkspace() throws IOException { - sourceDefinitionsHandler.revokeSourceDefinitionFromWorkspace(new SourceDefinitionIdWithWorkspaceId() - .sourceDefinitionId(sourceDefinition.getSourceDefinitionId()) - .workspaceId(workspaceId)); - verify(configRepository).deleteActorDefinitionWorkspaceGrant( - sourceDefinition.getSourceDefinitionId(), - workspaceId); - } - - @Nested - @DisplayName("listLatest") - class listLatest { - - @Test - @DisplayName("should return the latest list") - void testCorrect() throws IOException, InterruptedException { - final StandardSourceDefinition sourceDefinition = generateSourceDefinition(); - when(githubStore.getLatestSources()).thenReturn(Collections.singletonList(sourceDefinition)); - - final var sourceDefinitionReadList = sourceDefinitionsHandler.listLatestSourceDefinitions().getSourceDefinitions(); - assertEquals(1, sourceDefinitionReadList.size()); - - final var sourceDefinitionRead = sourceDefinitionReadList.get(0); - assertEquals(SourceDefinitionsHandler.buildSourceDefinitionRead(sourceDefinition), sourceDefinitionRead); - } - - @Test - @DisplayName("returns empty collection if cannot find latest definitions") - void testHttpTimeout() { - assertEquals(0, sourceDefinitionsHandler.listLatestSourceDefinitions().getSourceDefinitions().size()); - } - - @Test - @DisplayName("Icon should be an SVG icon") - void testIconHoldsData() { - final String icon = SourceDefinitionsHandler.loadIcon(sourceDefinition.getIcon()); - assertNotNull(icon); - assertTrue(icon.contains(" uuidGenerator; - private JsonSecretsProcessor secretsProcessor; - private ConnectorSpecification connectorSpecification; - private OAuthConfigSupplier oAuthConfigSupplier; - - private static final String SHOES = "shoes"; - private static final String SKU = "sku"; - private static final AirbyteCatalog airbyteCatalog = CatalogHelpers.createAirbyteCatalog(SHOES, - Field.of(SKU, JsonSchemaType.STRING)); - - // needs to match name of file in src/test/resources/icons - private static final String ICON = "test-source.svg"; - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() throws IOException { - configRepository = mock(ConfigRepository.class); - secretsRepositoryReader = mock(SecretsRepositoryReader.class); - secretsRepositoryWriter = mock(SecretsRepositoryWriter.class); - validator = mock(JsonSchemaValidator.class); - connectionsHandler = mock(ConnectionsHandler.class); - configurationUpdate = mock(ConfigurationUpdate.class); - uuidGenerator = mock(Supplier.class); - secretsProcessor = mock(JsonSecretsProcessor.class); - oAuthConfigSupplier = mock(OAuthConfigSupplier.class); - - connectorSpecification = ConnectorSpecificationHelpers.generateConnectorSpecification(); - - standardSourceDefinition = new StandardSourceDefinition() - .withSourceDefinitionId(UUID.randomUUID()) - .withName("marketo") - .withDockerRepository("thebestrepo") - .withDockerImageTag("thelatesttag") - .withDocumentationUrl("https://wikipedia.org") - .withSpec(connectorSpecification) - .withIcon(ICON); - - sourceDefinitionSpecificationRead = new SourceDefinitionSpecificationRead() - .sourceDefinitionId(standardSourceDefinition.getSourceDefinitionId()) - .connectionSpecification(connectorSpecification.getConnectionSpecification()) - .documentationUrl(connectorSpecification.getDocumentationUrl().toString()); - - sourceConnection = SourceHelpers.generateSource(standardSourceDefinition.getSourceDefinitionId()); - - sourceHandler = new SourceHandler(configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - validator, - connectionsHandler, - uuidGenerator, - secretsProcessor, - configurationUpdate, - oAuthConfigSupplier); - } - - @Test - void testCreateSource() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceCreate sourceCreate = new SourceCreate() - .name(sourceConnection.getName()) - .workspaceId(sourceConnection.getWorkspaceId()) - .sourceDefinitionId(standardSourceDefinition.getSourceDefinitionId()) - .connectionConfiguration(sourceConnection.getConfiguration()); - - when(uuidGenerator.get()).thenReturn(sourceConnection.getSourceId()); - when(configRepository.getSourceConnection(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(oAuthConfigSupplier.maskSourceOAuthParameters(sourceDefinitionSpecificationRead.getSourceDefinitionId(), sourceConnection.getWorkspaceId(), - sourceCreate.getConnectionConfiguration())).thenReturn(sourceCreate.getConnectionConfiguration()); - when(secretsProcessor.prepareSecretsForOutput(sourceCreate.getConnectionConfiguration(), - sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceCreate.getConnectionConfiguration()); - - final SourceRead actualSourceRead = sourceHandler.createSource(sourceCreate); - - final SourceRead expectedSourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition) - .connectionConfiguration(sourceConnection.getConfiguration()); - - assertEquals(expectedSourceRead, actualSourceRead); - - verify(secretsProcessor).prepareSecretsForOutput(sourceCreate.getConnectionConfiguration(), - sourceDefinitionSpecificationRead.getConnectionSpecification()); - verify(oAuthConfigSupplier).maskSourceOAuthParameters(sourceDefinitionSpecificationRead.getSourceDefinitionId(), - sourceConnection.getWorkspaceId(), sourceCreate.getConnectionConfiguration()); - verify(secretsRepositoryWriter).writeSourceConnection(sourceConnection, connectorSpecification); - verify(validator).ensure(sourceDefinitionSpecificationRead.getConnectionSpecification(), sourceConnection.getConfiguration()); - } - - @Test - void testUpdateSource() throws JsonValidationException, ConfigNotFoundException, IOException { - final String updatedSourceName = "my updated source name"; - final JsonNode newConfiguration = sourceConnection.getConfiguration(); - ((ObjectNode) newConfiguration).put("apiKey", "987-xyz"); - - final SourceConnection expectedSourceConnection = Jsons.clone(sourceConnection) - .withName(updatedSourceName) - .withConfiguration(newConfiguration) - .withTombstone(false); - - final SourceUpdate sourceUpdate = new SourceUpdate() - .name(updatedSourceName) - .sourceId(sourceConnection.getSourceId()) - .connectionConfiguration(newConfiguration); - - when(secretsProcessor - .copySecrets(sourceConnection.getConfiguration(), newConfiguration, sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(newConfiguration); - when(secretsProcessor.prepareSecretsForOutput(newConfiguration, sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(newConfiguration); - when(oAuthConfigSupplier.maskSourceOAuthParameters(sourceDefinitionSpecificationRead.getSourceDefinitionId(), sourceConnection.getWorkspaceId(), - newConfiguration)).thenReturn(newConfiguration); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceConnection(sourceConnection.getSourceId())) - .thenReturn(sourceConnection) - .thenReturn(expectedSourceConnection); - when(configurationUpdate.source(sourceConnection.getSourceId(), updatedSourceName, newConfiguration)) - .thenReturn(expectedSourceConnection); - - final SourceRead actualSourceRead = sourceHandler.updateSource(sourceUpdate); - final SourceRead expectedSourceRead = - SourceHelpers.getSourceRead(expectedSourceConnection, standardSourceDefinition).connectionConfiguration(newConfiguration); - - assertEquals(expectedSourceRead, actualSourceRead); - - verify(secretsProcessor).prepareSecretsForOutput(newConfiguration, sourceDefinitionSpecificationRead.getConnectionSpecification()); - verify(oAuthConfigSupplier).maskSourceOAuthParameters(sourceDefinitionSpecificationRead.getSourceDefinitionId(), - sourceConnection.getWorkspaceId(), newConfiguration); - verify(secretsRepositoryWriter).writeSourceConnection(expectedSourceConnection, connectorSpecification); - verify(validator).ensure(sourceDefinitionSpecificationRead.getConnectionSpecification(), newConfiguration); - } - - @Test - void testGetSource() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceRead expectedSourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition); - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(expectedSourceRead.getSourceId()); - - when(configRepository.getSourceConnection(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - final SourceRead actualSourceRead = sourceHandler.getSource(sourceIdRequestBody); - - assertEquals(expectedSourceRead, actualSourceRead); - - // make sure the icon was loaded into actual svg content - assertTrue(expectedSourceRead.getIcon().startsWith("")); - - verify(secretsProcessor).prepareSecretsForOutput(sourceConnection.getConfiguration(), - sourceDefinitionSpecificationRead.getConnectionSpecification()); - } - - @Test - void testCloneSourceWithoutConfigChange() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceConnection clonedConnection = SourceHelpers.generateSource(standardSourceDefinition.getSourceDefinitionId()); - final SourceRead expectedClonedSourceRead = SourceHelpers.getSourceRead(clonedConnection, standardSourceDefinition); - final SourceRead sourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition); - - final SourceCloneRequestBody sourceCloneRequestBody = new SourceCloneRequestBody().sourceCloneId(sourceRead.getSourceId()); - - when(uuidGenerator.get()).thenReturn(clonedConnection.getSourceId()); - when(secretsRepositoryReader.getSourceConnectionWithSecrets(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.getSourceConnection(clonedConnection.getSourceId())).thenReturn(clonedConnection); - - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - final SourceRead actualSourceRead = sourceHandler.cloneSource(sourceCloneRequestBody); - - assertEquals(expectedClonedSourceRead, actualSourceRead); - } - - @Test - void testCloneSourceWithConfigChange() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceConnection clonedConnection = SourceHelpers.generateSource(standardSourceDefinition.getSourceDefinitionId()); - final SourceRead expectedClonedSourceRead = SourceHelpers.getSourceRead(clonedConnection, standardSourceDefinition); - final SourceRead sourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition); - - final SourceCloneConfiguration sourceCloneConfiguration = new SourceCloneConfiguration().name("Copy Name"); - final SourceCloneRequestBody sourceCloneRequestBody = - new SourceCloneRequestBody().sourceCloneId(sourceRead.getSourceId()).sourceConfiguration(sourceCloneConfiguration); - - when(uuidGenerator.get()).thenReturn(clonedConnection.getSourceId()); - when(secretsRepositoryReader.getSourceConnectionWithSecrets(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.getSourceConnection(clonedConnection.getSourceId())).thenReturn(clonedConnection); - - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - final SourceRead actualSourceRead = sourceHandler.cloneSource(sourceCloneRequestBody); - - assertEquals(expectedClonedSourceRead, actualSourceRead); - } - - @Test - void testListSourcesForWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceRead expectedSourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition); - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(sourceConnection.getWorkspaceId()); - - when(configRepository.getSourceConnection(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.getSourceConnection(sourceConnection.getSourceId())).thenReturn(sourceConnection); - - when(configRepository.listWorkspaceSourceConnection(sourceConnection.getWorkspaceId())).thenReturn(Lists.newArrayList(sourceConnection)); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - final SourceReadList actualSourceReadList = sourceHandler.listSourcesForWorkspace(workspaceIdRequestBody); - - assertEquals(expectedSourceRead, actualSourceReadList.getSources().get(0)); - verify(secretsProcessor).prepareSecretsForOutput(sourceConnection.getConfiguration(), - sourceDefinitionSpecificationRead.getConnectionSpecification()); - } - - @Test - void testListSourcesForSourceDefinition() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceRead expectedSourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition); - final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody = - new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceConnection.getSourceDefinitionId()); - - when(configRepository.getSourceConnection(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.listSourcesForDefinition(sourceConnection.getSourceDefinitionId())).thenReturn(Lists.newArrayList(sourceConnection)); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - final SourceReadList actualSourceReadList = sourceHandler.listSourcesForSourceDefinition(sourceDefinitionIdRequestBody); - - assertEquals(expectedSourceRead, actualSourceReadList.getSources().get(0)); - verify(secretsProcessor).prepareSecretsForOutput(sourceConnection.getConfiguration(), - sourceDefinitionSpecificationRead.getConnectionSpecification()); - } - - @Test - void testSearchSources() throws JsonValidationException, ConfigNotFoundException, IOException { - final SourceRead expectedSourceRead = SourceHelpers.getSourceRead(sourceConnection, standardSourceDefinition); - - when(configRepository.getSourceConnection(sourceConnection.getSourceId())).thenReturn(sourceConnection); - when(configRepository.listSourceConnection()).thenReturn(Lists.newArrayList(sourceConnection)); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - when(connectionsHandler.matchSearch(new SourceSearch(), expectedSourceRead)).thenReturn(true); - SourceReadList actualSourceReadList = sourceHandler.searchSources(new SourceSearch()); - assertEquals(1, actualSourceReadList.getSources().size()); - assertEquals(expectedSourceRead, actualSourceReadList.getSources().get(0)); - - when(connectionsHandler.matchSearch(new SourceSearch(), expectedSourceRead)).thenReturn(false); - actualSourceReadList = sourceHandler.searchSources(new SourceSearch()); - assertEquals(0, actualSourceReadList.getSources().size()); - } - - @Test - void testDeleteSource() throws JsonValidationException, ConfigNotFoundException, IOException { - final JsonNode newConfiguration = sourceConnection.getConfiguration(); - ((ObjectNode) newConfiguration).put("apiKey", "987-xyz"); - - final SourceConnection expectedSourceConnection = Jsons.clone(sourceConnection).withTombstone(true); - - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(sourceConnection.getSourceId()); - final StandardSync standardSync = ConnectionHelpers.generateSyncWithSourceId(sourceConnection.getSourceId()); - final ConnectionRead connectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - final ConnectionReadList connectionReadList = new ConnectionReadList().connections(Collections.singletonList(connectionRead)); - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(sourceConnection.getWorkspaceId()); - - when(configRepository.getSourceConnection(sourceConnection.getSourceId())) - .thenReturn(sourceConnection) - .thenReturn(expectedSourceConnection); - when(secretsRepositoryReader.getSourceConnectionWithSecrets(sourceConnection.getSourceId())) - .thenReturn(sourceConnection) - .thenReturn(expectedSourceConnection); - when(oAuthConfigSupplier.maskSourceOAuthParameters(sourceDefinitionSpecificationRead.getSourceDefinitionId(), sourceConnection.getWorkspaceId(), - newConfiguration)).thenReturn(newConfiguration); - when(configRepository.getStandardSourceDefinition(sourceDefinitionSpecificationRead.getSourceDefinitionId())) - .thenReturn(standardSourceDefinition); - when(configRepository.getSourceDefinitionFromSource(sourceConnection.getSourceId())).thenReturn(standardSourceDefinition); - when(connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody)).thenReturn(connectionReadList); - when( - secretsProcessor.prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification())) - .thenReturn(sourceConnection.getConfiguration()); - - sourceHandler.deleteSource(sourceIdRequestBody); - - verify(secretsRepositoryWriter).writeSourceConnection(expectedSourceConnection, connectorSpecification); - verify(connectionsHandler).listConnectionsForWorkspace(workspaceIdRequestBody); - verify(connectionsHandler).deleteConnection(connectionRead.getConnectionId()); - } - - @Test - void testWriteDiscoverCatalogResult() throws JsonValidationException, IOException { - UUID actorId = UUID.randomUUID(); - UUID catalogId = UUID.randomUUID(); - String connectorVersion = "0.0.1"; - String hashValue = "0123456789abcd"; - final StandardSourceDefinition sourceDefinition = configRepository.getSourceDefinitionFromSource(actorId); - - SourceDiscoverSchemaWriteRequestBody request = new SourceDiscoverSchemaWriteRequestBody().catalog( - CatalogConverter.toApi(airbyteCatalog, sourceDefinition)).sourceId(actorId).connectorVersion(connectorVersion).configurationHash(hashValue); - - when(configRepository.writeActorCatalogFetchEvent(airbyteCatalog, actorId, connectorVersion, hashValue)).thenReturn(catalogId); - DiscoverCatalogResult result = sourceHandler.writeDiscoverCatalogResult(request); - - verify(configRepository).writeActorCatalogFetchEvent(airbyteCatalog, actorId, connectorVersion, hashValue); - assert (result.getCatalogId()).equals(catalogId); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/StateHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/StateHandlerTest.java deleted file mode 100644 index 381924a7e84c3..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/StateHandlerTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionState; -import io.airbyte.api.model.generated.ConnectionStateType; -import io.airbyte.api.model.generated.GlobalState; -import io.airbyte.api.model.generated.StreamState; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.json.Jsons; -import io.airbyte.config.StateType; -import io.airbyte.config.StateWrapper; -import io.airbyte.config.persistence.StatePersistence; -import io.airbyte.protocol.models.AirbyteGlobalState; -import io.airbyte.protocol.models.AirbyteStateMessage; -import io.airbyte.protocol.models.AirbyteStateMessage.AirbyteStateType; -import io.airbyte.protocol.models.AirbyteStreamState; -import io.airbyte.protocol.models.StreamDescriptor; -import io.airbyte.workers.helper.ProtocolConverters; -import java.io.IOException; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class StateHandlerTest { - - public static final UUID CONNECTION_ID = UUID.randomUUID(); - private static final JsonNode JSON_BLOB = Jsons.deserialize("{\"users\": 10}"); - public static final StreamDescriptor STREAM_DESCRIPTOR1 = new StreamDescriptor().withName("coffee"); - public static final StreamDescriptor STREAM_DESCRIPTOR2 = new StreamDescriptor().withName("tea"); - - private StateHandler stateHandler; - private StatePersistence statePersistence; - - @BeforeEach - void setup() { - statePersistence = mock(StatePersistence.class); - stateHandler = new StateHandler(statePersistence); - } - - @Test - void testGetCurrentStateEmpty() throws IOException { - when(statePersistence.getCurrentState(CONNECTION_ID)).thenReturn(Optional.empty()); - - final ConnectionState expected = new ConnectionState().connectionId(CONNECTION_ID).stateType(ConnectionStateType.NOT_SET).streamState(null); - final ConnectionState actual = stateHandler.getState(new ConnectionIdRequestBody().connectionId(CONNECTION_ID)); - assertEquals(expected, actual); - } - - @Test - void testGetLegacyState() throws IOException { - when(statePersistence.getCurrentState(CONNECTION_ID)).thenReturn(Optional.of( - new StateWrapper() - .withStateType(StateType.LEGACY) - .withLegacyState(JSON_BLOB))); - - final ConnectionState expected = new ConnectionState() - .connectionId(CONNECTION_ID) - .stateType(ConnectionStateType.LEGACY) - .streamState(null) - .state(JSON_BLOB); - final ConnectionState actual = stateHandler.getState(new ConnectionIdRequestBody().connectionId(CONNECTION_ID)); - assertEquals(expected, actual); - } - - @Test - void testGetGlobalState() throws IOException { - when(statePersistence.getCurrentState(CONNECTION_ID)).thenReturn(Optional.of( - new StateWrapper() - .withStateType(StateType.GLOBAL) - .withGlobal(new AirbyteStateMessage().withType(AirbyteStateType.GLOBAL).withGlobal(new AirbyteGlobalState() - .withSharedState(JSON_BLOB) - .withStreamStates(List.of( - new AirbyteStreamState().withStreamDescriptor(STREAM_DESCRIPTOR1).withStreamState(JSON_BLOB), - new AirbyteStreamState().withStreamDescriptor(STREAM_DESCRIPTOR2).withStreamState(JSON_BLOB))))))); - - final ConnectionState expected = new ConnectionState() - .connectionId(CONNECTION_ID) - .stateType(ConnectionStateType.GLOBAL) - .streamState(null) - .globalState(new GlobalState().sharedState(JSON_BLOB).streamStates(List.of( - new StreamState().streamDescriptor(ProtocolConverters.streamDescriptorToApi(STREAM_DESCRIPTOR1)).streamState(JSON_BLOB), - new StreamState().streamDescriptor(ProtocolConverters.streamDescriptorToApi(STREAM_DESCRIPTOR2)).streamState(JSON_BLOB)))); - final ConnectionState actual = stateHandler.getState(new ConnectionIdRequestBody().connectionId(CONNECTION_ID)); - assertEquals(expected, actual); - } - - @Test - void testGetStreamState() throws IOException { - when(statePersistence.getCurrentState(CONNECTION_ID)).thenReturn(Optional.of( - new StateWrapper() - .withStateType(StateType.STREAM) - .withStateMessages(List.of( - new AirbyteStateMessage() - .withType(AirbyteStateType.STREAM) - .withStream(new AirbyteStreamState().withStreamDescriptor(STREAM_DESCRIPTOR1).withStreamState(JSON_BLOB)), - new AirbyteStateMessage() - .withType(AirbyteStateType.STREAM) - .withStream(new AirbyteStreamState().withStreamDescriptor(STREAM_DESCRIPTOR2).withStreamState(JSON_BLOB)))))); - - final ConnectionState expected = new ConnectionState() - .connectionId(CONNECTION_ID) - .stateType(ConnectionStateType.STREAM) - .streamState(List.of( - new StreamState().streamDescriptor(ProtocolConverters.streamDescriptorToApi(STREAM_DESCRIPTOR1)).streamState(JSON_BLOB), - new StreamState().streamDescriptor(ProtocolConverters.streamDescriptorToApi(STREAM_DESCRIPTOR2)).streamState(JSON_BLOB))); - final ConnectionState actual = stateHandler.getState(new ConnectionIdRequestBody().connectionId(CONNECTION_ID)); - assertEquals(expected, actual); - } - - // the api type has an extra type, so the verifying the compatibility of the type conversion is more - // involved - @Test - void testEnumConversion() { - assertEquals(3, AirbyteStateType.class.getEnumConstants().length); - assertEquals(4, ConnectionStateType.class.getEnumConstants().length); - - // to AirbyteStateType => ConnectionStateType - assertEquals(ConnectionStateType.GLOBAL, Enums.convertTo(AirbyteStateType.GLOBAL, ConnectionStateType.class)); - assertEquals(ConnectionStateType.STREAM, Enums.convertTo(AirbyteStateType.STREAM, ConnectionStateType.class)); - assertEquals(ConnectionStateType.LEGACY, Enums.convertTo(AirbyteStateType.LEGACY, ConnectionStateType.class)); - - // to ConnectionStateType => AirbyteStateType - assertEquals(AirbyteStateType.GLOBAL, Enums.convertTo(ConnectionStateType.GLOBAL, AirbyteStateType.class)); - assertEquals(AirbyteStateType.STREAM, Enums.convertTo(ConnectionStateType.STREAM, AirbyteStateType.class)); - assertEquals(AirbyteStateType.LEGACY, Enums.convertTo(ConnectionStateType.LEGACY, AirbyteStateType.class)); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandlerTest.java deleted file mode 100644 index ff4db111593ce..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendCheckUpdatesHandlerTest.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import io.airbyte.api.model.generated.WebBackendCheckUpdatesRead; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.persistence.ConfigRepository; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class WebBackendCheckUpdatesHandlerTest { - - ConfigRepository configRepository; - AirbyteGithubStore githubStore; - WebBackendCheckUpdatesHandler webBackendCheckUpdatesHandler; - - final static boolean INCLUDE_TOMBSTONE = false; - - @BeforeEach - void beforeEach() { - configRepository = mock(ConfigRepository.class); - githubStore = mock(AirbyteGithubStore.class); - webBackendCheckUpdatesHandler = new WebBackendCheckUpdatesHandler(configRepository, githubStore); - } - - @Test - void testCheckWithoutUpdate() throws IOException, InterruptedException { - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final String sourceTag1 = "1.0.0"; - final String sourceTag2 = "2.0.0"; - - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - final String destTag1 = "0.1.0"; - final String destTag2 = "0.2.0"; - - setMocks( - List.of(Map.entry(source1, sourceTag1), Map.entry(source2, sourceTag2), Map.entry(source2, sourceTag2)), - List.of(Map.entry(source1, sourceTag1), Map.entry(source2, sourceTag2)), - List.of(Map.entry(dest1, destTag1), Map.entry(dest2, destTag2)), - List.of(Map.entry(dest1, destTag1), Map.entry(dest2, destTag2))); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(0).sourceDefinitions(0), actual); - } - - @Test - void testCheckWithUpdate() throws IOException, InterruptedException { - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final String sourceTag1 = "1.1.0"; - final String sourceTag2 = "2.1.0"; - - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - final String destTag1 = "0.1.0"; - final String destTag2 = "0.2.0"; - - setMocks( - List.of(Map.entry(source1, sourceTag1), Map.entry(source2, sourceTag2), Map.entry(source2, sourceTag2)), - List.of(Map.entry(source1, "1.1.1"), Map.entry(source2, sourceTag2)), - List.of(Map.entry(dest1, destTag1), Map.entry(dest2, destTag2), Map.entry(dest2, destTag2)), - List.of(Map.entry(dest1, destTag1), Map.entry(dest2, "0.3.0"))); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(2).sourceDefinitions(1), actual); - } - - @Test - void testCheckWithMissingActorDefFromLatest() throws IOException, InterruptedException { - final UUID source1 = UUID.randomUUID(); - final UUID source2 = UUID.randomUUID(); - final String sourceTag1 = "1.0.0"; - final String sourceTag2 = "2.0.0"; - - final UUID dest1 = UUID.randomUUID(); - final UUID dest2 = UUID.randomUUID(); - final String destTag1 = "0.1.0"; - final String destTag2 = "0.2.0"; - - setMocks( - List.of(Map.entry(source1, sourceTag1), Map.entry(source2, sourceTag2), Map.entry(source2, sourceTag2)), - List.of(Map.entry(source2, sourceTag2)), - List.of(Map.entry(dest1, destTag1), Map.entry(dest2, destTag2)), - List.of(Map.entry(dest1, destTag1))); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(0).sourceDefinitions(0), actual); - } - - @Test - void testCheckErrorNoCurrentDestinations() throws IOException, InterruptedException { - setMocksForExceptionCases(); - when(configRepository.listStandardDestinationDefinitions(INCLUDE_TOMBSTONE)).thenThrow(new IOException("unable to read current destinations")); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(0).sourceDefinitions(1), actual); - } - - @Test - void testCheckErrorNoCurrentSources() throws IOException, InterruptedException { - setMocksForExceptionCases(); - when(configRepository.listStandardSourceDefinitions(INCLUDE_TOMBSTONE)).thenThrow(new IOException("unable to read current sources")); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(1).sourceDefinitions(0), actual); - } - - @Test - void testCheckErrorNoLatestDestinations() throws IOException, InterruptedException { - setMocksForExceptionCases(); - when(githubStore.getLatestDestinations()).thenThrow(new InterruptedException("unable to read latest destinations")); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(0).sourceDefinitions(1), actual); - } - - @Test - void testCheckErrorNoLatestSources() throws IOException, InterruptedException { - setMocksForExceptionCases(); - when(githubStore.getLatestSources()).thenThrow(new InterruptedException("unable to read latest sources")); - - final WebBackendCheckUpdatesRead actual = webBackendCheckUpdatesHandler.checkUpdates(); - - assertEquals(new WebBackendCheckUpdatesRead().destinationDefinitions(1).sourceDefinitions(0), actual); - } - - private void setMocksForExceptionCases() throws IOException, InterruptedException { - final UUID source1 = UUID.randomUUID(); - final String sourceTag1 = source1.toString(); - - final UUID dest1 = UUID.randomUUID(); - final String destTag1 = dest1.toString(); - - setMocks( - List.of(Map.entry(source1, sourceTag1)), - List.of(Map.entry(source1, UUID.randomUUID().toString())), - List.of(Map.entry(dest1, destTag1)), - List.of(Map.entry(dest1, UUID.randomUUID().toString()))); - } - - private void setMocks(final List> currentSources, - final List> latestSources, - final List> currentDestinations, - final List> latestDestinations) - throws IOException, InterruptedException { - when(configRepository.listStandardSourceDefinitions(INCLUDE_TOMBSTONE)) - .thenReturn(currentSources.stream().map(this::createSourceDef).toList()); - when(githubStore.getLatestSources()) - .thenReturn(latestSources.stream().map(this::createSourceDef).toList()); - - when(configRepository.listStandardDestinationDefinitions(INCLUDE_TOMBSTONE)) - .thenReturn(currentDestinations.stream().map(this::createDestinationDef).toList()); - when(githubStore.getLatestDestinations()) - .thenReturn(latestDestinations.stream().map(this::createDestinationDef).toList()); - } - - private StandardDestinationDefinition createDestinationDef(final Entry idImageTagEntry) { - return new StandardDestinationDefinition() - .withDestinationDefinitionId(idImageTagEntry.getKey()) - .withDockerImageTag(idImageTagEntry.getValue()); - } - - private StandardSourceDefinition createSourceDef(final Entry idImageTagEntry) { - return new StandardSourceDefinition() - .withSourceDefinitionId(idImageTagEntry.getKey()) - .withDockerImageTag(idImageTagEntry.getValue()); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandlerTest.java deleted file mode 100644 index 83789d5b89fe4..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendConnectionsHandlerTest.java +++ /dev/null @@ -1,1396 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.AirbyteCatalog; -import io.airbyte.api.model.generated.AirbyteStream; -import io.airbyte.api.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.model.generated.AttemptRead; -import io.airbyte.api.model.generated.AttemptStatus; -import io.airbyte.api.model.generated.CatalogDiff; -import io.airbyte.api.model.generated.ConnectionCreate; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionSchedule; -import io.airbyte.api.model.generated.ConnectionSchedule.TimeUnitEnum; -import io.airbyte.api.model.generated.ConnectionState; -import io.airbyte.api.model.generated.ConnectionStateType; -import io.airbyte.api.model.generated.ConnectionStatus; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationSyncMode; -import io.airbyte.api.model.generated.FieldAdd; -import io.airbyte.api.model.generated.FieldRemove; -import io.airbyte.api.model.generated.FieldTransform; -import io.airbyte.api.model.generated.Geography; -import io.airbyte.api.model.generated.JobConfigType; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.JobRead; -import io.airbyte.api.model.generated.JobStatus; -import io.airbyte.api.model.generated.JobWithAttemptsRead; -import io.airbyte.api.model.generated.NamespaceDefinitionType; -import io.airbyte.api.model.generated.NonBreakingChangesPreference; -import io.airbyte.api.model.generated.OperationRead; -import io.airbyte.api.model.generated.OperationReadList; -import io.airbyte.api.model.generated.OperationUpdate; -import io.airbyte.api.model.generated.ResourceRequirements; -import io.airbyte.api.model.generated.SchemaChange; -import io.airbyte.api.model.generated.SelectedFieldInfo; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRequestBody; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.StreamDescriptor; -import io.airbyte.api.model.generated.StreamTransform; -import io.airbyte.api.model.generated.StreamTransform.TransformTypeEnum; -import io.airbyte.api.model.generated.SyncMode; -import io.airbyte.api.model.generated.SynchronousJobRead; -import io.airbyte.api.model.generated.WebBackendConnectionCreate; -import io.airbyte.api.model.generated.WebBackendConnectionListItem; -import io.airbyte.api.model.generated.WebBackendConnectionListRequestBody; -import io.airbyte.api.model.generated.WebBackendConnectionRead; -import io.airbyte.api.model.generated.WebBackendConnectionReadList; -import io.airbyte.api.model.generated.WebBackendConnectionRequestBody; -import io.airbyte.api.model.generated.WebBackendConnectionUpdate; -import io.airbyte.api.model.generated.WebBackendOperationCreateOrUpdate; -import io.airbyte.api.model.generated.WebBackendWorkspaceState; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.handlers.helpers.CatalogConverter; -import io.airbyte.commons.server.helpers.ConnectionHelpers; -import io.airbyte.commons.server.helpers.DestinationDefinitionHelpers; -import io.airbyte.commons.server.helpers.DestinationHelpers; -import io.airbyte.commons.server.helpers.SourceDefinitionHelpers; -import io.airbyte.commons.server.helpers.SourceHelpers; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.commons.temporal.TemporalClient.ManualOperationResult; -import io.airbyte.config.ActorCatalog; -import io.airbyte.config.ActorCatalogFetchEvent; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardDestinationDefinition; -import io.airbyte.config.StandardSourceDefinition; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.Status; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.ConfigRepository.DestinationAndDefinition; -import io.airbyte.config.persistence.ConfigRepository.SourceAndDefinition; -import io.airbyte.config.persistence.ConfigRepository.StandardSyncQuery; -import io.airbyte.protocol.models.CatalogHelpers; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.protocol.models.Field; -import io.airbyte.protocol.models.JsonSchemaType; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.lang.reflect.Method; -import java.time.Instant; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InOrder; - -class WebBackendConnectionsHandlerTest { - - private ConnectionsHandler connectionsHandler; - private OperationsHandler operationsHandler; - private SchedulerHandler schedulerHandler; - private StateHandler stateHandler; - private WebBackendConnectionsHandler wbHandler; - private SourceRead sourceRead; - private ConnectionRead connectionRead; - private ConnectionRead brokenConnectionRead; - private WebBackendConnectionListItem expectedListItem; - private OperationReadList operationReadList; - private OperationReadList brokenOperationReadList; - private WebBackendConnectionRead expected; - private WebBackendConnectionRead expectedWithNewSchema; - private WebBackendConnectionRead expectedWithNewSchemaAndBreakingChange; - private WebBackendConnectionRead expectedWithNewSchemaBroken; - private WebBackendConnectionRead expectedNoDiscoveryWithNewSchema; - private EventRunner eventRunner; - private ConfigRepository configRepository; - - private static final String STREAM1 = "stream1"; - private static final String STREAM2 = "stream2"; - private static final String FIELD1 = "field1"; - private static final String FIELD2 = "field2"; - private static final String FIELD3 = "field3"; - private static final String FIELD5 = "field5"; - - // needs to match name of file in src/test/resources/icons - private static final String SOURCE_ICON = "test-source.svg"; - private static final String DESTINATION_ICON = "test-destination.svg"; - private static final String SVG = ""; - - @BeforeEach - void setup() throws IOException, JsonValidationException, ConfigNotFoundException { - connectionsHandler = mock(ConnectionsHandler.class); - stateHandler = mock(StateHandler.class); - operationsHandler = mock(OperationsHandler.class); - final SourceHandler sourceHandler = mock(SourceHandler.class); - final DestinationHandler destinationHandler = mock(DestinationHandler.class); - final JobHistoryHandler jobHistoryHandler = mock(JobHistoryHandler.class); - configRepository = mock(ConfigRepository.class); - schedulerHandler = mock(SchedulerHandler.class); - eventRunner = mock(EventRunner.class); - wbHandler = new WebBackendConnectionsHandler( - connectionsHandler, - stateHandler, - sourceHandler, - destinationHandler, - jobHistoryHandler, - schedulerHandler, - operationsHandler, - eventRunner, - configRepository); - - final StandardSourceDefinition sourceDefinition = SourceDefinitionHelpers.generateSourceDefinition(); - sourceDefinition.setIcon(SOURCE_ICON); - final SourceConnection source = SourceHelpers.generateSource(sourceDefinition.getSourceDefinitionId()); - sourceRead = SourceHelpers.getSourceRead(source, sourceDefinition); - - final StandardDestinationDefinition destinationDefinition = DestinationDefinitionHelpers.generateDestination(); - destinationDefinition.setIcon(DESTINATION_ICON); - final DestinationConnection destination = DestinationHelpers.generateDestination(destinationDefinition.getDestinationDefinitionId()); - final DestinationRead destinationRead = DestinationHelpers.getDestinationRead(destination, destinationDefinition); - - final StandardSync standardSync = - ConnectionHelpers.generateSyncWithSourceAndDestinationId(source.getSourceId(), destination.getDestinationId(), false, Status.ACTIVE); - final StandardSync brokenStandardSync = - ConnectionHelpers.generateSyncWithSourceAndDestinationId(source.getSourceId(), destination.getDestinationId(), true, Status.INACTIVE); - - when(configRepository.listWorkspaceStandardSyncs(new StandardSyncQuery(sourceRead.getWorkspaceId(), null, null, false))) - .thenReturn(Collections.singletonList(standardSync)); - when(configRepository.getSourceAndDefinitionsFromSourceIds(Collections.singletonList(source.getSourceId()))) - .thenReturn(Collections.singletonList(new SourceAndDefinition(source, sourceDefinition))); - when(configRepository.getDestinationAndDefinitionsFromDestinationIds(Collections.singletonList(destination.getDestinationId()))) - .thenReturn(Collections.singletonList(new DestinationAndDefinition(destination, destinationDefinition))); - - connectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); - brokenConnectionRead = ConnectionHelpers.generateExpectedConnectionRead(brokenStandardSync); - operationReadList = new OperationReadList() - .operations(List.of(new OperationRead() - .operationId(connectionRead.getOperationIds().get(0)) - .name("Test Operation"))); - brokenOperationReadList = new OperationReadList() - .operations(List.of(new OperationRead() - .operationId(brokenConnectionRead.getOperationIds().get(0)) - .name("Test Operation"))); - - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody(); - sourceIdRequestBody.setSourceId(connectionRead.getSourceId()); - when(sourceHandler.getSource(sourceIdRequestBody)).thenReturn(sourceRead); - - final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody(); - destinationIdRequestBody.setDestinationId(connectionRead.getDestinationId()); - when(destinationHandler.getDestination(destinationIdRequestBody)).thenReturn(destinationRead); - - final Instant now = Instant.now(); - final JobWithAttemptsRead jobRead = new JobWithAttemptsRead() - .job(new JobRead() - .configId(connectionRead.getConnectionId().toString()) - .configType(JobConfigType.SYNC) - .id(10L) - .status(JobStatus.SUCCEEDED) - .createdAt(now.getEpochSecond()) - .updatedAt(now.getEpochSecond())) - .attempts(Lists.newArrayList(new AttemptRead() - .id(12L) - .status(AttemptStatus.SUCCEEDED) - .bytesSynced(100L) - .recordsSynced(15L) - .createdAt(now.getEpochSecond()) - .updatedAt(now.getEpochSecond()) - .endedAt(now.getEpochSecond()))); - - when(jobHistoryHandler.getLatestSyncJob(connectionRead.getConnectionId())).thenReturn(Optional.of(jobRead.getJob())); - - when(jobHistoryHandler.getLatestSyncJobsForConnections(Collections.singletonList(connectionRead.getConnectionId()))) - .thenReturn(Collections.singletonList(jobRead.getJob())); - - final JobWithAttemptsRead brokenJobRead = new JobWithAttemptsRead() - .job(new JobRead() - .configId(brokenConnectionRead.getConnectionId().toString()) - .configType(JobConfigType.SYNC) - .id(10L) - .status(JobStatus.SUCCEEDED) - .createdAt(now.getEpochSecond()) - .updatedAt(now.getEpochSecond())) - .attempts(Lists.newArrayList(new AttemptRead() - .id(12L) - .status(AttemptStatus.SUCCEEDED) - .bytesSynced(100L) - .recordsSynced(15L) - .createdAt(now.getEpochSecond()) - .updatedAt(now.getEpochSecond()) - .endedAt(now.getEpochSecond()))); - - when(jobHistoryHandler.getLatestSyncJob(brokenConnectionRead.getConnectionId())).thenReturn(Optional.of(brokenJobRead.getJob())); - - when(jobHistoryHandler.getLatestSyncJobsForConnections(Collections.singletonList(brokenConnectionRead.getConnectionId()))) - .thenReturn(Collections.singletonList(brokenJobRead.getJob())); - - expectedListItem = ConnectionHelpers.generateExpectedWebBackendConnectionListItem( - standardSync, - sourceRead, - destinationRead, - false, - jobRead.getJob().getCreatedAt(), - jobRead.getJob().getStatus(), - SchemaChange.NO_CHANGE); - - expected = expectedWebBackendConnectionReadObject(connectionRead, sourceRead, destinationRead, operationReadList, SchemaChange.NO_CHANGE, now, - connectionRead.getSyncCatalog(), connectionRead.getSourceCatalogId()); - expectedNoDiscoveryWithNewSchema = expectedWebBackendConnectionReadObject(connectionRead, sourceRead, destinationRead, operationReadList, - SchemaChange.NON_BREAKING, now, connectionRead.getSyncCatalog(), connectionRead.getSourceCatalogId()); - - final AirbyteCatalog modifiedCatalog = ConnectionHelpers.generateMultipleStreamsApiCatalog(2); - final SourceDiscoverSchemaRequestBody sourceDiscoverSchema = new SourceDiscoverSchemaRequestBody(); - sourceDiscoverSchema.setSourceId(connectionRead.getSourceId()); - sourceDiscoverSchema.setDisableCache(true); - when(schedulerHandler.discoverSchemaForSourceFromSourceId(sourceDiscoverSchema)).thenReturn( - new SourceDiscoverSchemaRead() - .jobInfo(mock(SynchronousJobRead.class)) - .catalog(modifiedCatalog)); - - expectedWithNewSchema = expectedWebBackendConnectionReadObject(connectionRead, sourceRead, destinationRead, - new OperationReadList().operations(expected.getOperations()), SchemaChange.NON_BREAKING, now, modifiedCatalog, null) - .catalogDiff(new CatalogDiff().transforms(List.of( - new StreamTransform().transformType(TransformTypeEnum.ADD_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name("users-data1")) - .updateStream(null)))); - - expectedWithNewSchemaAndBreakingChange = expectedWebBackendConnectionReadObject(brokenConnectionRead, sourceRead, destinationRead, - new OperationReadList().operations(expected.getOperations()), SchemaChange.BREAKING, now, modifiedCatalog, null) - .catalogDiff(new CatalogDiff().transforms(List.of( - new StreamTransform().transformType(TransformTypeEnum.ADD_STREAM) - .streamDescriptor(new io.airbyte.api.model.generated.StreamDescriptor().name("users-data1")) - .updateStream(null)))); - - expectedWithNewSchemaBroken = expectedWebBackendConnectionReadObject(brokenConnectionRead, sourceRead, destinationRead, brokenOperationReadList, - SchemaChange.BREAKING, now, connectionRead.getSyncCatalog(), brokenConnectionRead.getSourceCatalogId()); - when(schedulerHandler.resetConnection(any(ConnectionIdRequestBody.class))) - .thenReturn(new JobInfoRead().job(new JobRead().status(JobStatus.SUCCEEDED))); - } - - WebBackendConnectionRead expectedWebBackendConnectionReadObject( - final ConnectionRead connectionRead, - final SourceRead sourceRead, - final DestinationRead destinationRead, - final OperationReadList operationReadList, - final SchemaChange schemaChange, - final Instant now, - final AirbyteCatalog syncCatalog, - final UUID catalogId) { - return new WebBackendConnectionRead() - .connectionId(connectionRead.getConnectionId()) - .sourceId(connectionRead.getSourceId()) - .destinationId(connectionRead.getDestinationId()) - .operationIds(connectionRead.getOperationIds()) - .name(connectionRead.getName()) - .namespaceDefinition(connectionRead.getNamespaceDefinition()) - .namespaceFormat(connectionRead.getNamespaceFormat()) - .prefix(connectionRead.getPrefix()) - .syncCatalog(syncCatalog) - .catalogId(catalogId) - .status(connectionRead.getStatus()) - .schedule(connectionRead.getSchedule()) - .scheduleType(connectionRead.getScheduleType()) - .scheduleData(connectionRead.getScheduleData()) - .source(sourceRead) - .destination(destinationRead) - .operations(operationReadList.getOperations()) - .latestSyncJobCreatedAt(now.getEpochSecond()) - .latestSyncJobStatus(JobStatus.SUCCEEDED) - .isSyncing(false) - .schemaChange(schemaChange) - .resourceRequirements(new ResourceRequirements() - .cpuRequest(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getCpuRequest()) - .cpuLimit(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getCpuLimit()) - .memoryRequest(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getMemoryRequest()) - .memoryLimit(ConnectionHelpers.TESTING_RESOURCE_REQUIREMENTS.getMemoryLimit())); - } - - @Test - void testGetWorkspaceState() throws IOException { - final UUID uuid = UUID.randomUUID(); - final WebBackendWorkspaceState request = new WebBackendWorkspaceState().workspaceId(uuid); - when(configRepository.countSourcesForWorkspace(uuid)).thenReturn(5); - when(configRepository.countDestinationsForWorkspace(uuid)).thenReturn(2); - when(configRepository.countConnectionsForWorkspace(uuid)).thenReturn(8); - final var actual = wbHandler.getWorkspaceState(request); - assertTrue(actual.getHasConnections()); - assertTrue(actual.getHasDestinations()); - assertTrue((actual.getHasSources())); - } - - @Test - void testGetWorkspaceStateEmpty() throws IOException { - final UUID uuid = UUID.randomUUID(); - final WebBackendWorkspaceState request = new WebBackendWorkspaceState().workspaceId(uuid); - when(configRepository.countSourcesForWorkspace(uuid)).thenReturn(0); - when(configRepository.countDestinationsForWorkspace(uuid)).thenReturn(0); - when(configRepository.countConnectionsForWorkspace(uuid)).thenReturn(0); - final var actual = wbHandler.getWorkspaceState(request); - assertFalse(actual.getHasConnections()); - assertFalse(actual.getHasDestinations()); - assertFalse(actual.getHasSources()); - } - - @Test - void testWebBackendListConnectionsForWorkspace() throws IOException, JsonValidationException, ConfigNotFoundException { - final WebBackendConnectionListRequestBody webBackendConnectionListRequestBody = new WebBackendConnectionListRequestBody(); - webBackendConnectionListRequestBody.setWorkspaceId(sourceRead.getWorkspaceId()); - - final WebBackendConnectionReadList WebBackendConnectionReadList = - wbHandler.webBackendListConnectionsForWorkspace(webBackendConnectionListRequestBody); - - assertEquals(1, WebBackendConnectionReadList.getConnections().size()); - assertEquals(expectedListItem, WebBackendConnectionReadList.getConnections().get(0)); - - // make sure the icons were loaded into actual svg content - assertTrue(expectedListItem.getSource().getIcon().startsWith(SVG)); - assertTrue(expectedListItem.getDestination().getIcon().startsWith(SVG)); - } - - @Test - void testWebBackendGetConnection() throws ConfigNotFoundException, IOException, JsonValidationException { - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody(); - connectionIdRequestBody.setConnectionId(connectionRead.getConnectionId()); - - final WebBackendConnectionRequestBody webBackendConnectionRequestBody = new WebBackendConnectionRequestBody(); - webBackendConnectionRequestBody.setConnectionId(connectionRead.getConnectionId()); - - when(connectionsHandler.getConnection(connectionRead.getConnectionId())).thenReturn(connectionRead); - when(operationsHandler.listOperationsForConnection(connectionIdRequestBody)).thenReturn(operationReadList); - - final WebBackendConnectionRead webBackendConnectionRead = wbHandler.webBackendGetConnection(webBackendConnectionRequestBody); - - assertEquals(expected, webBackendConnectionRead); - - // make sure the icons were loaded into actual svg content - assertTrue(expected.getSource().getIcon().startsWith(SVG)); - assertTrue(expected.getDestination().getIcon().startsWith(SVG)); - } - - WebBackendConnectionRead testWebBackendGetConnection(final boolean withCatalogRefresh, - final ConnectionRead connectionRead, - final OperationReadList operationReadList) - throws JsonValidationException, ConfigNotFoundException, IOException { - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody(); - connectionIdRequestBody.setConnectionId(connectionRead.getConnectionId()); - - final WebBackendConnectionRequestBody webBackendConnectionIdRequestBody = new WebBackendConnectionRequestBody(); - webBackendConnectionIdRequestBody.setConnectionId(connectionRead.getConnectionId()); - if (withCatalogRefresh) { - webBackendConnectionIdRequestBody.setWithRefreshedCatalog(true); - } - - when(connectionsHandler.getConnection(connectionRead.getConnectionId())).thenReturn(connectionRead); - when(operationsHandler.listOperationsForConnection(connectionIdRequestBody)).thenReturn(operationReadList); - - return wbHandler.webBackendGetConnection(webBackendConnectionIdRequestBody); - } - - @Test - void testWebBackendGetConnectionWithDiscoveryAndNewSchema() throws ConfigNotFoundException, - IOException, JsonValidationException { - final UUID newCatalogId = UUID.randomUUID(); - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(newCatalogId))); - when(configRepository.getActorCatalogById(any())).thenReturn(new ActorCatalog().withId(UUID.randomUUID())); - final SourceDiscoverSchemaRead schemaRead = - new SourceDiscoverSchemaRead().catalogDiff(expectedWithNewSchema.getCatalogDiff()).catalog(expectedWithNewSchema.getSyncCatalog()) - .breakingChange(false).connectionStatus(ConnectionStatus.ACTIVE); - when(schedulerHandler.discoverSchemaForSourceFromSourceId(any())).thenReturn(schemaRead); - when(connectionsHandler.getConnectionAirbyteCatalog(connectionRead.getConnectionId())).thenReturn(Optional.of(connectionRead.getSyncCatalog())); - - final WebBackendConnectionRead result = testWebBackendGetConnection(true, connectionRead, - operationReadList); - assertEquals(expectedWithNewSchema, result); - } - - @Test - void testWebBackendGetConnectionWithDiscoveryAndNewSchemaBreakingChange() throws ConfigNotFoundException, - IOException, JsonValidationException { - final UUID newCatalogId = UUID.randomUUID(); - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(newCatalogId))); - when(configRepository.getActorCatalogById(any())).thenReturn(new ActorCatalog().withId(UUID.randomUUID())); - final SourceDiscoverSchemaRead schemaRead = - new SourceDiscoverSchemaRead().catalogDiff(expectedWithNewSchema.getCatalogDiff()).catalog(expectedWithNewSchema.getSyncCatalog()) - .breakingChange(true).connectionStatus(ConnectionStatus.INACTIVE); - when(schedulerHandler.discoverSchemaForSourceFromSourceId(any())).thenReturn(schemaRead); - when(connectionsHandler.getConnectionAirbyteCatalog(brokenConnectionRead.getConnectionId())) - .thenReturn(Optional.of(connectionRead.getSyncCatalog())); - - final WebBackendConnectionRead result = testWebBackendGetConnection(true, brokenConnectionRead, - operationReadList); - assertEquals(expectedWithNewSchemaAndBreakingChange, result); - } - - @Test - void testWebBackendGetConnectionWithDiscoveryMissingCatalogUsedToMakeConfiguredCatalog() - throws IOException, ConfigNotFoundException, JsonValidationException { - final UUID newCatalogId = UUID.randomUUID(); - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(newCatalogId))); - when(configRepository.getActorCatalogById(any())).thenReturn(new ActorCatalog().withId(UUID.randomUUID())); - final SourceDiscoverSchemaRead schemaRead = - new SourceDiscoverSchemaRead().catalogDiff(expectedWithNewSchema.getCatalogDiff()).catalog(expectedWithNewSchema.getSyncCatalog()) - .breakingChange(false).connectionStatus(ConnectionStatus.ACTIVE); - when(schedulerHandler.discoverSchemaForSourceFromSourceId(any())).thenReturn(schemaRead); - when(connectionsHandler.getConnectionAirbyteCatalog(connectionRead.getConnectionId())).thenReturn(Optional.empty()); - - final WebBackendConnectionRead result = testWebBackendGetConnection(true, connectionRead, - operationReadList); - assertEquals(expectedWithNewSchema, result); - } - - @Test - void testWebBackendGetConnectionWithDiscoveryAndFieldSelectionAddField() throws ConfigNotFoundException, - IOException, JsonValidationException { - // Mock this because the API uses it to determine whether there was a schema change. - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(UUID.randomUUID()))); - - // Original configured catalog has two fields, and only one of them is selected. - final AirbyteCatalog originalConfiguredCatalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - originalConfiguredCatalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem( - ConnectionHelpers.FIELD_NAME))); - connectionRead.syncCatalog(originalConfiguredCatalog); - - // Original discovered catalog has the same two fields but no selection info because it's a - // discovered catalog. - when(connectionsHandler.getConnectionAirbyteCatalog(connectionRead.getConnectionId())).thenReturn( - Optional.of(ConnectionHelpers.generateApiCatalogWithTwoFields())); - - // Newly-discovered catalog has an extra field. There is no field selection info because it's a - // discovered catalog. - final AirbyteCatalog newCatalogToDiscover = ConnectionHelpers.generateApiCatalogWithTwoFields(); - final JsonNode newFieldSchema = Jsons.deserialize("{\"type\": \"string\"}"); - ((ObjectNode) newCatalogToDiscover.getStreams().get(0).getStream().getJsonSchema().findPath("properties")) - .putObject("a-new-field") - .put("type", "string"); - final SourceDiscoverSchemaRead schemaRead = - new SourceDiscoverSchemaRead() - .catalogDiff( - new CatalogDiff().addTransformsItem(new StreamTransform().addUpdateStreamItem(new FieldTransform().transformType( - FieldTransform.TransformTypeEnum.ADD_FIELD).addFieldNameItem("a-new-field").breaking(false) - .addField(new FieldAdd().schema(newFieldSchema))))) - .catalog(newCatalogToDiscover) - .breakingChange(false) - .connectionStatus(ConnectionStatus.ACTIVE); - when(schedulerHandler.discoverSchemaForSourceFromSourceId(any())).thenReturn(schemaRead); - - final WebBackendConnectionRead result = testWebBackendGetConnection(true, connectionRead, - operationReadList); - - // We expect the discovered catalog with two fields selected: the one that was originally selected, - // plus the newly-discovered field. - final AirbyteCatalog expectedNewCatalog = Jsons.clone(newCatalogToDiscover); - expectedNewCatalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).selectedFields( - List.of(new SelectedFieldInfo().addFieldPathItem(ConnectionHelpers.FIELD_NAME), new SelectedFieldInfo().addFieldPathItem("a-new-field"))); - expectedWithNewSchema.catalogDiff(schemaRead.getCatalogDiff()).syncCatalog(expectedNewCatalog); - assertEquals(expectedWithNewSchema, result); - } - - @Test - void testWebBackendGetConnectionWithDiscoveryAndFieldSelectionRemoveField() throws ConfigNotFoundException, - IOException, JsonValidationException { - // Mock this because the API uses it to determine whether there was a schema change. - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(UUID.randomUUID()))); - - // Original configured catalog has two fields, and both of them are selected. - final AirbyteCatalog originalConfiguredCatalog = ConnectionHelpers.generateApiCatalogWithTwoFields(); - originalConfiguredCatalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true) - .selectedFields(List.of(new SelectedFieldInfo().addFieldPathItem( - ConnectionHelpers.FIELD_NAME), new SelectedFieldInfo().addFieldPathItem(ConnectionHelpers.FIELD_NAME + "2"))); - connectionRead.syncCatalog(originalConfiguredCatalog); - - // Original discovered catalog has the same two fields but no selection info because it's a - // discovered catalog. - when(connectionsHandler.getConnectionAirbyteCatalog(connectionRead.getConnectionId())).thenReturn( - Optional.of(ConnectionHelpers.generateApiCatalogWithTwoFields())); - - // Newly-discovered catalog has one of the fields removed. There is no field selection info because - // it's a - // discovered catalog. - final AirbyteCatalog newCatalogToDiscover = ConnectionHelpers.generateBasicApiCatalog(); - final JsonNode removedFieldSchema = Jsons.deserialize("{\"type\": \"string\"}"); - final SourceDiscoverSchemaRead schemaRead = - new SourceDiscoverSchemaRead() - .catalogDiff(new CatalogDiff().addTransformsItem(new StreamTransform().addUpdateStreamItem( - new FieldTransform().transformType(FieldTransform.TransformTypeEnum.REMOVE_FIELD).addFieldNameItem(ConnectionHelpers.FIELD_NAME + "2") - .breaking(false).removeField(new FieldRemove().schema(removedFieldSchema))))) - .catalog(newCatalogToDiscover) - .breakingChange(false) - .connectionStatus(ConnectionStatus.ACTIVE); - when(schedulerHandler.discoverSchemaForSourceFromSourceId(any())).thenReturn(schemaRead); - - final WebBackendConnectionRead result = testWebBackendGetConnection(true, connectionRead, - operationReadList); - - // We expect the discovered catalog with two fields selected: the one that was originally selected, - // plus the newly-discovered field. - final AirbyteCatalog expectedNewCatalog = Jsons.clone(newCatalogToDiscover); - expectedNewCatalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).selectedFields( - List.of(new SelectedFieldInfo().addFieldPathItem(ConnectionHelpers.FIELD_NAME))); - expectedWithNewSchema.catalogDiff(schemaRead.getCatalogDiff()).syncCatalog(expectedNewCatalog); - assertEquals(expectedWithNewSchema, result); - } - - @Test - void testWebBackendGetConnectionNoRefreshCatalog() - throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionRead result = testWebBackendGetConnection(false, connectionRead, operationReadList); - verify(schedulerHandler, never()).discoverSchemaForSourceFromSourceId(any()); - assertEquals(expected, result); - } - - @Test - void testWebBackendGetConnectionNoDiscoveryWithNewSchema() throws JsonValidationException, ConfigNotFoundException, IOException { - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(UUID.randomUUID()))); - when(configRepository.getActorCatalogById(any())).thenReturn(new ActorCatalog().withId(UUID.randomUUID())); - final WebBackendConnectionRead result = testWebBackendGetConnection(false, connectionRead, operationReadList); - assertEquals(expectedNoDiscoveryWithNewSchema, result); - } - - @Test - void testWebBackendGetConnectionNoDiscoveryWithNewSchemaBreaking() throws JsonValidationException, ConfigNotFoundException, IOException { - when(connectionsHandler.getConnection(brokenConnectionRead.getConnectionId())).thenReturn(brokenConnectionRead); - when(configRepository.getMostRecentActorCatalogFetchEventForSource(any())) - .thenReturn(Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(UUID.randomUUID()))); - when(configRepository.getActorCatalogById(any())).thenReturn(new ActorCatalog().withId(UUID.randomUUID())); - final WebBackendConnectionRead result = testWebBackendGetConnection(false, brokenConnectionRead, brokenOperationReadList); - assertEquals(expectedWithNewSchemaBroken, result); - } - - @Test - void testToConnectionCreate() throws IOException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final StandardSync standardSync = ConnectionHelpers.generateSyncWithSourceId(source.getSourceId()); - - final AirbyteCatalog catalog = ConnectionHelpers.generateBasicApiCatalog(); - catalog.getStreams().get(0).getStream().setName("azkaban_users"); - - final ConnectionSchedule schedule = new ConnectionSchedule().units(1L).timeUnit(TimeUnitEnum.MINUTES); - - final UUID newSourceId = UUID.randomUUID(); - final UUID newDestinationId = UUID.randomUUID(); - final UUID newOperationId = UUID.randomUUID(); - final UUID sourceCatalogId = UUID.randomUUID(); - final WebBackendConnectionCreate input = new WebBackendConnectionCreate() - .name("testConnectionCreate") - .namespaceDefinition(Enums.convertTo(standardSync.getNamespaceDefinition(), NamespaceDefinitionType.class)) - .namespaceFormat(standardSync.getNamespaceFormat()) - .prefix(standardSync.getPrefix()) - .sourceId(newSourceId) - .destinationId(newDestinationId) - .operationIds(List.of(newOperationId)) - .status(ConnectionStatus.INACTIVE) - .schedule(schedule) - .syncCatalog(catalog) - .sourceCatalogId(sourceCatalogId) - .geography(Geography.US) - .nonBreakingChangesPreference(NonBreakingChangesPreference.DISABLE); - - final List operationIds = List.of(newOperationId); - - final ConnectionCreate expected = new ConnectionCreate() - .name("testConnectionCreate") - .namespaceDefinition(Enums.convertTo(standardSync.getNamespaceDefinition(), NamespaceDefinitionType.class)) - .namespaceFormat(standardSync.getNamespaceFormat()) - .prefix(standardSync.getPrefix()) - .sourceId(newSourceId) - .destinationId(newDestinationId) - .operationIds(operationIds) - .status(ConnectionStatus.INACTIVE) - .schedule(schedule) - .syncCatalog(catalog) - .sourceCatalogId(sourceCatalogId) - .geography(Geography.US) - .nonBreakingChangesPreference(NonBreakingChangesPreference.DISABLE); - - final ConnectionCreate actual = WebBackendConnectionsHandler.toConnectionCreate(input, operationIds); - - assertEquals(expected, actual); - } - - @Test - void testToConnectionPatch() throws IOException { - final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); - final StandardSync standardSync = ConnectionHelpers.generateSyncWithSourceId(source.getSourceId()); - - final AirbyteCatalog catalog = ConnectionHelpers.generateBasicApiCatalog(); - catalog.getStreams().get(0).getStream().setName("azkaban_users"); - - final ConnectionSchedule schedule = new ConnectionSchedule().units(1L).timeUnit(TimeUnitEnum.MINUTES); - - final UUID newOperationId = UUID.randomUUID(); - final WebBackendConnectionUpdate input = new WebBackendConnectionUpdate() - .namespaceDefinition(Enums.convertTo(standardSync.getNamespaceDefinition(), NamespaceDefinitionType.class)) - .namespaceFormat(standardSync.getNamespaceFormat()) - .prefix(standardSync.getPrefix()) - .connectionId(standardSync.getConnectionId()) - .operations(List.of(new WebBackendOperationCreateOrUpdate().operationId(newOperationId))) - .status(ConnectionStatus.INACTIVE) - .schedule(schedule) - .name(standardSync.getName()) - .syncCatalog(catalog) - .geography(Geography.US) - .nonBreakingChangesPreference(NonBreakingChangesPreference.DISABLE) - .notifySchemaChanges(false); - - final List operationIds = List.of(newOperationId); - - final ConnectionUpdate expected = new ConnectionUpdate() - .namespaceDefinition(Enums.convertTo(standardSync.getNamespaceDefinition(), NamespaceDefinitionType.class)) - .namespaceFormat(standardSync.getNamespaceFormat()) - .prefix(standardSync.getPrefix()) - .connectionId(standardSync.getConnectionId()) - .operationIds(operationIds) - .status(ConnectionStatus.INACTIVE) - .schedule(schedule) - .name(standardSync.getName()) - .syncCatalog(catalog) - .geography(Geography.US) - .nonBreakingChangesPreference(NonBreakingChangesPreference.DISABLE) - .notifySchemaChanges(false) - .breakingChange(false); - - final ConnectionUpdate actual = WebBackendConnectionsHandler.toConnectionPatch(input, operationIds, false); - - assertEquals(expected, actual); - } - - @Test - void testForConnectionCreateCompleteness() { - final Set handledMethods = - Set.of("name", "namespaceDefinition", "namespaceFormat", "prefix", "sourceId", "destinationId", "operationIds", - "addOperationIdsItem", "removeOperationIdsItem", "syncCatalog", "schedule", "scheduleType", "scheduleData", - "status", "resourceRequirements", "sourceCatalogId", "geography", "nonBreakingChangesPreference", "notifySchemaChanges"); - - final Set methods = Arrays.stream(ConnectionCreate.class.getMethods()) - .filter(method -> method.getReturnType() == ConnectionCreate.class) - .map(Method::getName) - .collect(Collectors.toSet()); - - final String message = - """ - If this test is failing, it means you added a field to ConnectionCreate! - Congratulations, but you're not done yet.. - \tYou should update WebBackendConnectionsHandler::toConnectionCreate - \tand ensure that the field is tested in WebBackendConnectionsHandlerTest::testToConnectionCreate - Then you can add the field name here to make this test pass. Cheers!"""; - assertEquals(handledMethods, methods, message); - } - - @Test - void testForConnectionPatchCompleteness() { - final Set handledMethods = - Set.of("schedule", "connectionId", "syncCatalog", "namespaceDefinition", "namespaceFormat", "prefix", "status", - "operationIds", "addOperationIdsItem", "removeOperationIdsItem", "resourceRequirements", "name", - "sourceCatalogId", "scheduleType", "scheduleData", "geography", "breakingChange", "notifySchemaChanges", "nonBreakingChangesPreference"); - - final Set methods = Arrays.stream(ConnectionUpdate.class.getMethods()) - .filter(method -> method.getReturnType() == ConnectionUpdate.class) - .map(Method::getName) - .collect(Collectors.toSet()); - - final String message = - """ - If this test is failing, it means you added a field to ConnectionUpdate! - Congratulations, but you're not done yet.. - \tYou should update WebBackendConnectionsHandler::toConnectionPatch - \tand ensure that the field is tested in WebBackendConnectionsHandlerTest::testToConnectionPatch - Then you can add the field name here to make this test pass. Cheers!"""; - assertEquals(handledMethods, methods, message); - } - - @Test - void testUpdateConnection() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expected.getSyncCatalog()) - .sourceCatalogId(expected.getCatalogId()); - - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()); - - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of()); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(expected.getConnectionId()); - when(stateHandler.getState(connectionIdRequestBody)).thenReturn(new ConnectionState().stateType(ConnectionStateType.LEGACY)); - - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead().connectionId(expected.getConnectionId())); - when(connectionsHandler.updateConnection(any())).thenReturn( - new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expected.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()).breakingChange(false)); - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - final ConnectionIdRequestBody connectionId = new ConnectionIdRequestBody().connectionId(connectionRead.getConnectionId()); - - final AirbyteCatalog fullAirbyteCatalog = ConnectionHelpers.generateMultipleStreamsApiCatalog(2); - when(connectionsHandler.getConnectionAirbyteCatalog(connectionRead.getConnectionId())).thenReturn(Optional.ofNullable(fullAirbyteCatalog)); - - final AirbyteCatalog expectedCatalogReturned = - WebBackendConnectionsHandler.updateSchemaWithRefreshedDiscoveredCatalog(expected.getSyncCatalog(), expected.getSyncCatalog(), - fullAirbyteCatalog); - final WebBackendConnectionRead connectionRead = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(expectedCatalogReturned, connectionRead.getSyncCatalog()); - - verify(schedulerHandler, times(0)).resetConnection(connectionId); - verify(schedulerHandler, times(0)).syncConnection(connectionId); - } - - @Test - void testUpdateConnectionWithOperations() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendOperationCreateOrUpdate operationCreateOrUpdate = new WebBackendOperationCreateOrUpdate() - .name("Test Operation") - .operationId(connectionRead.getOperationIds().get(0)); - final OperationUpdate operationUpdate = WebBackendConnectionsHandler.toOperationUpdate(operationCreateOrUpdate); - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expected.getSyncCatalog()) - .operations(List.of(operationCreateOrUpdate)); - - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()); - - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of()); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(expected.getConnectionId()); - when(stateHandler.getState(connectionIdRequestBody)).thenReturn(new ConnectionState().stateType(ConnectionStateType.LEGACY)); - - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead() - .connectionId(expected.getConnectionId()) - .operationIds(connectionRead.getOperationIds()) - .breakingChange(false)); - when(connectionsHandler.updateConnection(any())).thenReturn( - new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .operationIds(connectionRead.getOperationIds()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expected.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()).breakingChange(false)); - when(operationsHandler.updateOperation(operationUpdate)).thenReturn(new OperationRead().operationId(operationUpdate.getOperationId())); - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - - final WebBackendConnectionRead actualConnectionRead = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(connectionRead.getOperationIds(), actualConnectionRead.getOperationIds()); - verify(operationsHandler, times(1)).updateOperation(operationUpdate); - } - - @Test - void testUpdateConnectionWithUpdatedSchemaLegacy() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()); - - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(expected.getConnectionId()); - - when(stateHandler.getState(connectionIdRequestBody)).thenReturn(new ConnectionState().stateType(ConnectionStateType.LEGACY)); - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()); - - final StreamDescriptor streamDescriptorAdd = new StreamDescriptor().name("addStream"); - final StreamTransform streamTransformAdd = - new StreamTransform().streamDescriptor(streamDescriptorAdd).transformType(TransformTypeEnum.ADD_STREAM); - - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of(streamTransformAdd)); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead().connectionId(expected.getConnectionId())); - final ConnectionRead connectionRead = new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()).breakingChange(false); - when(connectionsHandler.updateConnection(any())).thenReturn(connectionRead); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn(connectionRead); - - final List connectionStreams = List.of(ConnectionHelpers.STREAM_DESCRIPTOR); - when(configRepository.getAllStreamsForConnection(expected.getConnectionId())).thenReturn(connectionStreams); - - final ManualOperationResult successfulResult = ManualOperationResult.builder().jobId(Optional.empty()).failingReason(Optional.empty()).build(); - when(eventRunner.resetConnection(any(), any(), anyBoolean())).thenReturn(successfulResult); - when(eventRunner.startNewManualSync(any())).thenReturn(successfulResult); - - final WebBackendConnectionRead result = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(expectedWithNewSchema.getSyncCatalog(), result.getSyncCatalog()); - - final ConnectionIdRequestBody connectionId = new ConnectionIdRequestBody().connectionId(result.getConnectionId()); - verify(schedulerHandler, times(0)).resetConnection(connectionId); - verify(schedulerHandler, times(0)).syncConnection(connectionId); - verify(connectionsHandler, times(1)).updateConnection(any()); - final InOrder orderVerifier = inOrder(eventRunner); - orderVerifier.verify(eventRunner, times(1)).resetConnection(connectionId.getConnectionId(), connectionStreams, true); - } - - @Test - void testUpdateConnectionWithUpdatedSchemaPerStream() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()); - - // state is per-stream - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(expected.getConnectionId()); - when(stateHandler.getState(connectionIdRequestBody)).thenReturn(new ConnectionState().stateType(ConnectionStateType.STREAM)); - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()); - - final StreamDescriptor streamDescriptorAdd = new StreamDescriptor().name("addStream"); - final StreamDescriptor streamDescriptorRemove = new StreamDescriptor().name("removeStream"); - final StreamDescriptor streamDescriptorUpdate = new StreamDescriptor().name("updateStream"); - - final StreamTransform streamTransformAdd = - new StreamTransform().streamDescriptor(streamDescriptorAdd).transformType(TransformTypeEnum.ADD_STREAM); - final StreamTransform streamTransformRemove = - new StreamTransform().streamDescriptor(streamDescriptorRemove).transformType(TransformTypeEnum.REMOVE_STREAM); - final StreamTransform streamTransformUpdate = - new StreamTransform().streamDescriptor(streamDescriptorUpdate).transformType(TransformTypeEnum.UPDATE_STREAM); - - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of(streamTransformAdd, streamTransformRemove, streamTransformUpdate)); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - when(connectionsHandler.getConfigurationDiff(any(), any())).thenReturn(Set.of(new StreamDescriptor().name("configUpdateStream"))); - - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead().connectionId(expected.getConnectionId()).breakingChange(false)); - final ConnectionRead connectionRead = new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()) - .breakingChange(false); - when(connectionsHandler.updateConnection(any())).thenReturn(connectionRead); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn(connectionRead); - - final ManualOperationResult successfulResult = ManualOperationResult.builder().jobId(Optional.empty()).failingReason(Optional.empty()).build(); - when(eventRunner.resetConnection(any(), any(), anyBoolean())).thenReturn(successfulResult); - when(eventRunner.startNewManualSync(any())).thenReturn(successfulResult); - - final WebBackendConnectionRead result = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(expectedWithNewSchema.getSyncCatalog(), result.getSyncCatalog()); - - final ConnectionIdRequestBody connectionId = new ConnectionIdRequestBody().connectionId(result.getConnectionId()); - verify(schedulerHandler, times(0)).resetConnection(connectionId); - verify(schedulerHandler, times(0)).syncConnection(connectionId); - verify(connectionsHandler, times(1)).updateConnection(any()); - final InOrder orderVerifier = inOrder(eventRunner); - orderVerifier.verify(eventRunner, times(1)).resetConnection(connectionId.getConnectionId(), - List.of(new io.airbyte.protocol.models.StreamDescriptor().withName("addStream"), - new io.airbyte.protocol.models.StreamDescriptor().withName("updateStream"), - new io.airbyte.protocol.models.StreamDescriptor().withName("configUpdateStream"), - new io.airbyte.protocol.models.StreamDescriptor().withName("removeStream")), - true); - } - - @Test - void testUpdateConnectionNoStreamsToReset() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()); - - // state is per-stream - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(expected.getConnectionId()); - final ConfiguredAirbyteCatalog configuredAirbyteCatalog = ConnectionHelpers.generateBasicConfiguredAirbyteCatalog(); - when(stateHandler.getState(connectionIdRequestBody)).thenReturn(new ConnectionState().stateType(ConnectionStateType.STREAM)); - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(configuredAirbyteCatalog); - - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of()); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff); - - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead().connectionId(expected.getConnectionId())); - final ConnectionRead connectionRead = new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()).breakingChange(false); - when(connectionsHandler.updateConnection(any())).thenReturn(connectionRead); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn(connectionRead); - - final WebBackendConnectionRead result = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(expectedWithNewSchema.getSyncCatalog(), result.getSyncCatalog()); - - final ConnectionIdRequestBody connectionId = new ConnectionIdRequestBody().connectionId(result.getConnectionId()); - - verify(connectionsHandler).getDiff(expected.getSyncCatalog(), expectedWithNewSchema.getSyncCatalog(), - CatalogConverter.toConfiguredProtocol(result.getSyncCatalog())); - verify(connectionsHandler).getConfigurationDiff(expected.getSyncCatalog(), expectedWithNewSchema.getSyncCatalog()); - verify(schedulerHandler, times(0)).resetConnection(connectionId); - verify(schedulerHandler, times(0)).syncConnection(connectionId); - verify(connectionsHandler, times(1)).updateConnection(any()); - final InOrder orderVerifier = inOrder(eventRunner); - orderVerifier.verify(eventRunner, times(0)).resetConnection(eq(connectionId.getConnectionId()), any(), anyBoolean()); - orderVerifier.verify(eventRunner, times(0)).startNewManualSync(connectionId.getConnectionId()); - } - - @Test - void testUpdateConnectionWithSkipReset() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .skipReset(true); - - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()); - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead().connectionId(expected.getConnectionId())); - final ConnectionRead connectionRead = new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()) - .breakingChange(false); - when(connectionsHandler.updateConnection(any())).thenReturn(connectionRead); - - final WebBackendConnectionRead result = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(expectedWithNewSchema.getSyncCatalog(), result.getSyncCatalog()); - - final ConnectionIdRequestBody connectionId = new ConnectionIdRequestBody().connectionId(result.getConnectionId()); - verify(schedulerHandler, times(0)).resetConnection(connectionId); - verify(schedulerHandler, times(0)).syncConnection(connectionId); - verify(connectionsHandler, times(0)).getDiff(any(), any(), any()); - verify(connectionsHandler, times(1)).updateConnection(any()); - verify(eventRunner, times(0)).resetConnection(any(), any(), eq(true)); - } - - @Test - void testUpdateConnectionFixingBreakingSchemaChange() throws JsonValidationException, ConfigNotFoundException, IOException { - final WebBackendConnectionUpdate updateBody = new WebBackendConnectionUpdate() - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .connectionId(expected.getConnectionId()) - .schedule(expected.getSchedule()) - .status(expected.getStatus()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .skipReset(false) - .connectionId(expected.getConnectionId()); - - final UUID sourceId = UUID.randomUUID(); - - // existing connection has a breaking change - when(connectionsHandler.getConnection(expected.getConnectionId())).thenReturn( - new ConnectionRead().connectionId(expected.getConnectionId()).breakingChange(true).sourceId(sourceId)); - - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of()); - - when(configRepository.getMostRecentActorCatalogForSource(sourceId)).thenReturn(Optional.of(new ActorCatalog().withCatalog(Jsons.deserialize( - "{\"streams\": [{\"name\": \"cat_names\", \"namespace\": \"public\", \"json_schema\": {\"type\": \"object\", \"properties\": {\"id\": {\"type\": \"number\", \"airbyte_type\": \"integer\"}}}}]}")))); - when(connectionsHandler.getDiff(any(), any(), any())).thenReturn(catalogDiff, catalogDiff); - - when(configRepository.getConfiguredCatalogForConnection(expected.getConnectionId())) - .thenReturn(ConnectionHelpers.generateBasicConfiguredAirbyteCatalog()); - when(operationsHandler.listOperationsForConnection(any())).thenReturn(operationReadList); - - final ConnectionRead connectionRead = new ConnectionRead() - .connectionId(expected.getConnectionId()) - .sourceId(expected.getSourceId()) - .destinationId(expected.getDestinationId()) - .name(expected.getName()) - .namespaceDefinition(expected.getNamespaceDefinition()) - .namespaceFormat(expected.getNamespaceFormat()) - .prefix(expected.getPrefix()) - .syncCatalog(expectedWithNewSchema.getSyncCatalog()) - .status(expected.getStatus()) - .schedule(expected.getSchedule()) - .breakingChange(false); - - when(connectionsHandler.updateConnection(any())).thenReturn(connectionRead); - - final WebBackendConnectionRead result = wbHandler.webBackendUpdateConnection(updateBody); - - assertEquals(expectedWithNewSchema.getSyncCatalog(), result.getSyncCatalog()); - - final ConnectionIdRequestBody connectionId = new ConnectionIdRequestBody().connectionId(result.getConnectionId()); - ArgumentCaptor expectedArgumentCaptor = ArgumentCaptor.forClass(ConnectionUpdate.class); - verify(connectionsHandler, times(1)).updateConnection(expectedArgumentCaptor.capture()); - List connectionUpdateValues = expectedArgumentCaptor.getAllValues(); - // Expect the ConnectionUpdate object to have breakingChange: false - assertEquals(false, connectionUpdateValues.get(0).getBreakingChange()); - - verify(schedulerHandler, times(0)).resetConnection(connectionId); - verify(schedulerHandler, times(0)).syncConnection(connectionId); - verify(connectionsHandler, times(2)).getDiff(any(), any(), any()); - verify(connectionsHandler, times(1)).updateConnection(any()); - } - - @Test - void testUpdateSchemaWithDiscoveryFromEmpty() { - final AirbyteCatalog original = new AirbyteCatalog().streams(List.of()); - final AirbyteCatalog discovered = ConnectionHelpers.generateBasicApiCatalog(); - discovered.getStreams().get(0).getStream() - .name(STREAM1) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD1, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH)); - discovered.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1); - - final AirbyteCatalog expected = ConnectionHelpers.generateBasicApiCatalog(); - expected.getStreams().get(0).getStream() - .name(STREAM1) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD1, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH)); - expected.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1) - .setSelected(false); - - final AirbyteCatalog actual = WebBackendConnectionsHandler.updateSchemaWithRefreshedDiscoveredCatalog(original, original, discovered); - - assertEquals(expected, actual); - } - - @Test - void testUpdateSchemaWithDiscoveryResetStream() { - final AirbyteCatalog original = ConnectionHelpers.generateBasicApiCatalog(); - original.getStreams().get(0).getStream() - .name("random-stream") - .defaultCursorField(List.of(FIELD1)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema( - Field.of(FIELD1, JsonSchemaType.NUMBER), - Field.of(FIELD2, JsonSchemaType.NUMBER), - Field.of(FIELD5, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - original.getStreams().get(0).getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(FIELD1)) - .destinationSyncMode(DestinationSyncMode.APPEND) - .primaryKey(Collections.emptyList()) - .aliasName("random_stream"); - - final AirbyteCatalog discovered = ConnectionHelpers.generateBasicApiCatalog(); - discovered.getStreams().get(0).getStream() - .name(STREAM1) - .defaultCursorField(List.of(FIELD3)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD2, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - discovered.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1); - - final AirbyteCatalog expected = ConnectionHelpers.generateBasicApiCatalog(); - expected.getStreams().get(0).getStream() - .name(STREAM1) - .defaultCursorField(List.of(FIELD3)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD2, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - expected.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1) - .setSelected(false); - - final AirbyteCatalog actual = WebBackendConnectionsHandler.updateSchemaWithRefreshedDiscoveredCatalog(original, original, discovered); - - assertEquals(expected, actual); - } - - @Test - void testUpdateSchemaWithDiscoveryMergeNewStream() { - final AirbyteCatalog original = ConnectionHelpers.generateBasicApiCatalog(); - original.getStreams().get(0).getStream() - .name(STREAM1) - .defaultCursorField(List.of(FIELD1)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema( - Field.of(FIELD1, JsonSchemaType.NUMBER), - Field.of(FIELD2, JsonSchemaType.NUMBER), - Field.of(FIELD5, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - original.getStreams().get(0).getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(FIELD1)) - .destinationSyncMode(DestinationSyncMode.APPEND) - .primaryKey(Collections.emptyList()) - .aliasName("renamed_stream"); - - final AirbyteCatalog discovered = ConnectionHelpers.generateBasicApiCatalog(); - discovered.getStreams().get(0).getStream() - .name(STREAM1) - .defaultCursorField(List.of(FIELD3)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD2, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - discovered.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1); - final AirbyteStreamAndConfiguration newStream = ConnectionHelpers.generateBasicApiCatalog().getStreams().get(0); - newStream.getStream() - .name(STREAM2) - .defaultCursorField(List.of(FIELD5)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD5, JsonSchemaType.BOOLEAN))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH)); - newStream.getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM2); - discovered.getStreams().add(newStream); - - final AirbyteCatalog expected = ConnectionHelpers.generateBasicApiCatalog(); - expected.getStreams().get(0).getStream() - .name(STREAM1) - .defaultCursorField(List.of(FIELD3)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD2, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - expected.getStreams().get(0).getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(FIELD1)) - .destinationSyncMode(DestinationSyncMode.APPEND) - .primaryKey(Collections.emptyList()) - .aliasName("renamed_stream") - .setSelected(true); - final AirbyteStreamAndConfiguration expectedNewStream = ConnectionHelpers.generateBasicApiCatalog().getStreams().get(0); - expectedNewStream.getStream() - .name(STREAM2) - .defaultCursorField(List.of(FIELD5)) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD5, JsonSchemaType.BOOLEAN))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH)); - expectedNewStream.getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM2) - .setSelected(false); - expected.getStreams().add(expectedNewStream); - - final AirbyteCatalog actual = WebBackendConnectionsHandler.updateSchemaWithRefreshedDiscoveredCatalog(original, original, discovered); - - assertEquals(expected, actual); - } - - @Test - void testUpdateSchemaWithNamespacedStreams() { - final AirbyteCatalog original = ConnectionHelpers.generateBasicApiCatalog(); - final AirbyteStreamAndConfiguration stream1Config = original.getStreams().get(0); - final AirbyteStream stream1 = stream1Config.getStream(); - final AirbyteStream stream2 = new AirbyteStream() - .name(stream1.getName()) - .namespace("second_namespace") - .jsonSchema(stream1.getJsonSchema()) - .defaultCursorField(stream1.getDefaultCursorField()) - .supportedSyncModes(stream1.getSupportedSyncModes()) - .sourceDefinedCursor(stream1.getSourceDefinedCursor()) - .sourceDefinedPrimaryKey(stream1.getSourceDefinedPrimaryKey()); - final AirbyteStreamAndConfiguration stream2Config = new AirbyteStreamAndConfiguration() - .config(stream1Config.getConfig()) - .stream(stream2); - original.getStreams().add(stream2Config); - - final AirbyteCatalog discovered = ConnectionHelpers.generateBasicApiCatalog(); - discovered.getStreams().get(0).getStream() - .name(STREAM1) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD1, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH)); - discovered.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1); - - final AirbyteCatalog expected = ConnectionHelpers.generateBasicApiCatalog(); - expected.getStreams().get(0).getStream() - .name(STREAM1) - .jsonSchema(CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD1, JsonSchemaType.STRING))) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH)); - expected.getStreams().get(0).getConfig() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.OVERWRITE) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM1) - .setSelected(false); - - final AirbyteCatalog actual = WebBackendConnectionsHandler.updateSchemaWithRefreshedDiscoveredCatalog(original, original, discovered); - - assertEquals(expected, actual); - } - - @Test - void testGetStreamsToReset() { - final StreamTransform streamTransformAdd = - new StreamTransform().transformType(TransformTypeEnum.ADD_STREAM).streamDescriptor(new StreamDescriptor().name("added_stream")); - final StreamTransform streamTransformRemove = - new StreamTransform().transformType(TransformTypeEnum.REMOVE_STREAM).streamDescriptor(new StreamDescriptor().name("removed_stream")); - final StreamTransform streamTransformUpdate = - new StreamTransform().transformType(TransformTypeEnum.UPDATE_STREAM).streamDescriptor(new StreamDescriptor().name("updated_stream")); - final CatalogDiff catalogDiff = new CatalogDiff().transforms(List.of(streamTransformAdd, streamTransformRemove, streamTransformUpdate)); - final List resultList = WebBackendConnectionsHandler.getStreamsToReset(catalogDiff); - assertTrue( - resultList.stream().anyMatch( - streamDescriptor -> "added_stream".equalsIgnoreCase(streamDescriptor.getName()))); - assertTrue( - resultList.stream().anyMatch( - streamDescriptor -> "removed_stream".equalsIgnoreCase(streamDescriptor.getName()))); - assertTrue( - resultList.stream().anyMatch( - streamDescriptor -> "updated_stream".equalsIgnoreCase(streamDescriptor.getName()))); - } - - @Test - void testGetSchemaChangeNoChange() { - final ConnectionRead connectionReadNotBreaking = new ConnectionRead().breakingChange(false); - - assertEquals(SchemaChange.NO_CHANGE, wbHandler.getSchemaChange(null, Optional.of(UUID.randomUUID()), Optional.of(new ActorCatalogFetchEvent()))); - assertEquals(SchemaChange.NO_CHANGE, - wbHandler.getSchemaChange(connectionReadNotBreaking, Optional.empty(), Optional.of(new ActorCatalogFetchEvent()))); - - final UUID catalogId = UUID.randomUUID(); - - assertEquals(SchemaChange.NO_CHANGE, wbHandler.getSchemaChange(connectionReadNotBreaking, Optional.of(catalogId), - Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(catalogId)))); - } - - @Test - void testGetSchemaChangeBreaking() { - final UUID sourceId = UUID.randomUUID(); - final ConnectionRead connectionReadWithSourceId = new ConnectionRead().sourceCatalogId(UUID.randomUUID()).sourceId(sourceId).breakingChange(true); - - assertEquals(SchemaChange.BREAKING, wbHandler.getSchemaChange(connectionReadWithSourceId, - Optional.of(UUID.randomUUID()), Optional.empty())); - } - - @Test - void testGetSchemaChangeNotBreaking() { - final UUID catalogId = UUID.randomUUID(); - final UUID differentCatalogId = UUID.randomUUID(); - final ConnectionRead connectionReadWithSourceId = - new ConnectionRead().breakingChange(false); - - assertEquals(SchemaChange.NON_BREAKING, wbHandler.getSchemaChange(connectionReadWithSourceId, - Optional.of(catalogId), Optional.of(new ActorCatalogFetchEvent().withActorCatalogId(differentCatalogId)))); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandlerTest.java deleted file mode 100644 index 2db572a7eabbf..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WebBackendGeographiesHandlerTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import io.airbyte.api.model.generated.Geography; -import io.airbyte.api.model.generated.WebBackendGeographiesListResult; -import java.util.List; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class WebBackendGeographiesHandlerTest { - - private WebBackendGeographiesHandler webBackendGeographiesHandler; - - @BeforeEach - void setUp() { - webBackendGeographiesHandler = new WebBackendGeographiesHandler(); - } - - @Test - void testListGeographiesOSS() { - final WebBackendGeographiesListResult expected = new WebBackendGeographiesListResult().geographies( - List.of(Geography.AUTO)); - - final WebBackendGeographiesListResult actual = webBackendGeographiesHandler.listGeographiesOSS(); - - Assertions.assertEquals(expected, actual); - } - - @Test - void testListGeographiesCloud() { - final WebBackendGeographiesListResult expected = new WebBackendGeographiesListResult().geographies( - List.of(Geography.AUTO, Geography.US, Geography.EU)); - - final WebBackendGeographiesListResult actual = webBackendGeographiesHandler.listGeographiesCloud(); - - Assertions.assertEquals(expected, actual); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WorkspacesHandlerTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WorkspacesHandlerTest.java deleted file mode 100644 index ab05041e4e74c..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/WorkspacesHandlerTest.java +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationReadList; -import io.airbyte.api.model.generated.SlugRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceReadList; -import io.airbyte.api.model.generated.WebhookConfigRead; -import io.airbyte.api.model.generated.WebhookConfigWrite; -import io.airbyte.api.model.generated.WorkspaceCreate; -import io.airbyte.api.model.generated.WorkspaceGiveFeedback; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.api.model.generated.WorkspaceRead; -import io.airbyte.api.model.generated.WorkspaceReadList; -import io.airbyte.api.model.generated.WorkspaceUpdate; -import io.airbyte.api.model.generated.WorkspaceUpdateName; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.converters.NotificationConverter; -import io.airbyte.config.Geography; -import io.airbyte.config.Notification; -import io.airbyte.config.Notification.NotificationType; -import io.airbyte.config.SlackNotificationConfiguration; -import io.airbyte.config.StandardWorkspace; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.function.Supplier; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -class WorkspacesHandlerTest { - - private static final String FAILURE_NOTIFICATION_WEBHOOK = "http://airbyte.notifications/failure"; - private static final String NEW_WORKSPACE = "new workspace"; - private static final String TEST_NAME = "test-name"; - - private static final String TEST_AUTH_TOKEN = "test-auth-token"; - private static final UUID WEBHOOK_CONFIG_ID = UUID.randomUUID(); - private static final JsonNode PERSISTED_WEBHOOK_CONFIGS = Jsons.deserialize( - String.format("{\"webhookConfigs\": [{\"id\": \"%s\", \"name\": \"%s\", \"authToken\": {\"_secret\": \"a-secret_v1\"}}]}", - WEBHOOK_CONFIG_ID, TEST_NAME)); - public static final String UPDATED = "updated"; - private ConfigRepository configRepository; - private SecretsRepositoryWriter secretsRepositoryWriter; - private ConnectionsHandler connectionsHandler; - private DestinationHandler destinationHandler; - private SourceHandler sourceHandler; - private Supplier uuidSupplier; - private StandardWorkspace workspace; - private WorkspacesHandler workspacesHandler; - - private static final String TEST_EMAIL = "test@airbyte.io"; - private static final String TEST_WORKSPACE_NAME = "test workspace"; - private static final String TEST_WORKSPACE_SLUG = "test-workspace"; - - private static final io.airbyte.api.model.generated.Geography GEOGRAPHY_AUTO = - io.airbyte.api.model.generated.Geography.AUTO; - private static final io.airbyte.api.model.generated.Geography GEOGRAPHY_US = - io.airbyte.api.model.generated.Geography.US; - private SecretPersistence secretPersistence; - - @SuppressWarnings("unchecked") - @BeforeEach - void setUp() { - configRepository = mock(ConfigRepository.class); - secretPersistence = mock(SecretPersistence.class); - secretsRepositoryWriter = new SecretsRepositoryWriter(configRepository, Optional.of(secretPersistence), Optional.empty()); - connectionsHandler = mock(ConnectionsHandler.class); - destinationHandler = mock(DestinationHandler.class); - sourceHandler = mock(SourceHandler.class); - uuidSupplier = mock(Supplier.class); - - workspace = generateWorkspace(); - workspacesHandler = new WorkspacesHandler(configRepository, secretsRepositoryWriter, connectionsHandler, - destinationHandler, sourceHandler, uuidSupplier); - } - - private StandardWorkspace generateWorkspace() { - return new StandardWorkspace() - .withWorkspaceId(UUID.randomUUID()) - .withCustomerId(UUID.randomUUID()) - .withEmail(TEST_EMAIL) - .withName(TEST_WORKSPACE_NAME) - .withSlug(TEST_WORKSPACE_SLUG) - .withInitialSetupComplete(false) - .withDisplaySetupWizard(true) - .withNews(false) - .withAnonymousDataCollection(false) - .withSecurityUpdates(false) - .withTombstone(false) - .withNotifications(List.of(generateNotification())) - .withDefaultGeography(Geography.AUTO); - } - - private Notification generateNotification() { - return new Notification() - .withNotificationType(NotificationType.SLACK) - .withSlackConfiguration(new SlackNotificationConfiguration() - .withWebhook(FAILURE_NOTIFICATION_WEBHOOK)); - } - - private io.airbyte.api.model.generated.Notification generateApiNotification() { - return new io.airbyte.api.model.generated.Notification() - .notificationType(io.airbyte.api.model.generated.NotificationType.SLACK) - .slackConfiguration(new io.airbyte.api.model.generated.SlackNotificationConfiguration() - .webhook(FAILURE_NOTIFICATION_WEBHOOK)); - } - - @Test - void testCreateWorkspace() throws JsonValidationException, IOException, ConfigNotFoundException { - workspace.withWebhookOperationConfigs(PERSISTED_WEBHOOK_CONFIGS); - when(configRepository.getStandardWorkspaceNoSecrets(any(), eq(false))).thenReturn(workspace); - - final UUID uuid = UUID.randomUUID(); - when(uuidSupplier.get()).thenReturn(uuid); - - configRepository.writeStandardWorkspaceNoSecrets(workspace); - - final WorkspaceCreate workspaceCreate = new WorkspaceCreate() - .name(NEW_WORKSPACE) - .email(TEST_EMAIL) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_US) - .webhookConfigs(List.of(new WebhookConfigWrite().name(TEST_NAME).authToken(TEST_AUTH_TOKEN))); - - final WorkspaceRead actualRead = workspacesHandler.createWorkspace(workspaceCreate); - final WorkspaceRead expectedRead = new WorkspaceRead() - .workspaceId(uuid) - .customerId(uuid) - .email(TEST_EMAIL) - .name(NEW_WORKSPACE) - .slug("new-workspace") - .initialSetupComplete(false) - .displaySetupWizard(false) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_US) - .webhookConfigs(List.of(new WebhookConfigRead().id(uuid).name(TEST_NAME))); - - assertEquals(expectedRead, actualRead); - } - - @Test - void testCreateWorkspaceDuplicateSlug() throws JsonValidationException, IOException, ConfigNotFoundException { - when(configRepository.getWorkspaceBySlugOptional(any(String.class), eq(true))) - .thenReturn(Optional.of(workspace)) - .thenReturn(Optional.of(workspace)) - .thenReturn(Optional.empty()); - when(configRepository.getStandardWorkspaceNoSecrets(any(), eq(false))).thenReturn(workspace); - - final UUID uuid = UUID.randomUUID(); - when(uuidSupplier.get()).thenReturn(uuid); - - configRepository.writeStandardWorkspaceNoSecrets(workspace); - - final WorkspaceCreate workspaceCreate = new WorkspaceCreate() - .name(workspace.getName()) - .email(TEST_EMAIL) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(Collections.emptyList()); - - final WorkspaceRead actualRead = workspacesHandler.createWorkspace(workspaceCreate); - final WorkspaceRead expectedRead = new WorkspaceRead() - .workspaceId(uuid) - .customerId(uuid) - .email(TEST_EMAIL) - .name(workspace.getName()) - .slug(workspace.getSlug()) - .initialSetupComplete(false) - .displaySetupWizard(false) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(Collections.emptyList()) - .defaultGeography(GEOGRAPHY_AUTO) - .webhookConfigs(Collections.emptyList()); - - assertTrue(actualRead.getSlug().startsWith(workspace.getSlug())); - assertNotEquals(workspace.getSlug(), actualRead.getSlug()); - assertEquals(Jsons.clone(expectedRead).slug(null), Jsons.clone(actualRead).slug(null)); - final ArgumentCaptor slugCaptor = ArgumentCaptor.forClass(String.class); - verify(configRepository, times(3)).getWorkspaceBySlugOptional(slugCaptor.capture(), eq(true)); - assertEquals(3, slugCaptor.getAllValues().size()); - assertEquals(workspace.getSlug(), slugCaptor.getAllValues().get(0)); - assertTrue(slugCaptor.getAllValues().get(1).startsWith(workspace.getSlug())); - assertTrue(slugCaptor.getAllValues().get(2).startsWith(workspace.getSlug())); - - } - - @Test - void testDeleteWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(workspace.getWorkspaceId()); - - final ConnectionRead connection = new ConnectionRead(); - final DestinationRead destination = new DestinationRead(); - final SourceRead source = new SourceRead(); - - when(configRepository.getStandardWorkspaceNoSecrets(workspace.getWorkspaceId(), false)).thenReturn(workspace); - - when(configRepository.listStandardWorkspaces(false)).thenReturn(Collections.singletonList(workspace)); - - when(connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody)) - .thenReturn(new ConnectionReadList().connections(Collections.singletonList(connection))); - - when(destinationHandler.listDestinationsForWorkspace(workspaceIdRequestBody)) - .thenReturn(new DestinationReadList().destinations(Collections.singletonList(destination))); - - when(sourceHandler.listSourcesForWorkspace(workspaceIdRequestBody)) - .thenReturn(new SourceReadList().sources(Collections.singletonList(source))); - - workspacesHandler.deleteWorkspace(workspaceIdRequestBody); - - verify(connectionsHandler).deleteConnection(connection.getConnectionId()); - verify(destinationHandler).deleteDestination(destination); - verify(sourceHandler).deleteSource(source); - } - - @Test - void testListWorkspaces() throws JsonValidationException, IOException { - final StandardWorkspace workspace2 = generateWorkspace(); - - when(configRepository.listStandardWorkspaces(false)).thenReturn(Lists.newArrayList(workspace, workspace2)); - - final WorkspaceRead expectedWorkspaceRead1 = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(workspace.getEmail()) - .name(workspace.getName()) - .slug(workspace.getSlug()) - .initialSetupComplete(workspace.getInitialSetupComplete()) - .displaySetupWizard(workspace.getDisplaySetupWizard()) - .news(workspace.getNews()) - .anonymousDataCollection(workspace.getAnonymousDataCollection()) - .securityUpdates(workspace.getSecurityUpdates()) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_AUTO); - - final WorkspaceRead expectedWorkspaceRead2 = new WorkspaceRead() - .workspaceId(workspace2.getWorkspaceId()) - .customerId(workspace2.getCustomerId()) - .email(workspace2.getEmail()) - .name(workspace2.getName()) - .slug(workspace2.getSlug()) - .initialSetupComplete(workspace2.getInitialSetupComplete()) - .displaySetupWizard(workspace2.getDisplaySetupWizard()) - .news(workspace2.getNews()) - .anonymousDataCollection(workspace2.getAnonymousDataCollection()) - .securityUpdates(workspace2.getSecurityUpdates()) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_AUTO); - - final WorkspaceReadList actualWorkspaceReadList = workspacesHandler.listWorkspaces(); - - assertEquals(Lists.newArrayList(expectedWorkspaceRead1, expectedWorkspaceRead2), - actualWorkspaceReadList.getWorkspaces()); - } - - @Test - void testGetWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - workspace.withWebhookOperationConfigs(PERSISTED_WEBHOOK_CONFIGS); - when(configRepository.getStandardWorkspaceNoSecrets(workspace.getWorkspaceId(), false)).thenReturn(workspace); - - final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(workspace.getWorkspaceId()); - - final WorkspaceRead workspaceRead = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(TEST_EMAIL) - .name(TEST_WORKSPACE_NAME) - .slug(TEST_WORKSPACE_SLUG) - .initialSetupComplete(false) - .displaySetupWizard(true) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_AUTO) - .webhookConfigs(List.of(new WebhookConfigRead().id(WEBHOOK_CONFIG_ID).name(TEST_NAME))); - - assertEquals(workspaceRead, workspacesHandler.getWorkspace(workspaceIdRequestBody)); - } - - @Test - void testGetWorkspaceBySlug() throws JsonValidationException, ConfigNotFoundException, IOException { - when(configRepository.getWorkspaceBySlug("default", false)).thenReturn(workspace); - - final SlugRequestBody slugRequestBody = new SlugRequestBody().slug("default"); - final WorkspaceRead workspaceRead = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(TEST_EMAIL) - .name(workspace.getName()) - .slug(workspace.getSlug()) - .initialSetupComplete(workspace.getInitialSetupComplete()) - .displaySetupWizard(workspace.getDisplaySetupWizard()) - .news(workspace.getNews()) - .anonymousDataCollection(workspace.getAnonymousDataCollection()) - .securityUpdates(workspace.getSecurityUpdates()) - .notifications(NotificationConverter.toApiList(workspace.getNotifications())) - .defaultGeography(GEOGRAPHY_AUTO); - - assertEquals(workspaceRead, workspacesHandler.getWorkspaceBySlug(slugRequestBody)); - } - - @Test - void testGetWorkspaceByConnectionId() { - final UUID connectionId = UUID.randomUUID(); - when(configRepository.getStandardWorkspaceFromConnection(connectionId, false)).thenReturn(workspace); - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody().connectionId(connectionId); - final WorkspaceRead workspaceRead = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(TEST_EMAIL) - .name(workspace.getName()) - .slug(workspace.getSlug()) - .initialSetupComplete(workspace.getInitialSetupComplete()) - .displaySetupWizard(workspace.getDisplaySetupWizard()) - .news(workspace.getNews()) - .anonymousDataCollection(workspace.getAnonymousDataCollection()) - .securityUpdates(workspace.getSecurityUpdates()) - .notifications(NotificationConverter.toApiList(workspace.getNotifications())) - .defaultGeography(GEOGRAPHY_AUTO); - - assertEquals(workspaceRead, workspacesHandler.getWorkspaceByConnectionId(connectionIdRequestBody)); - } - - @Test - void testUpdateWorkspace() throws JsonValidationException, ConfigNotFoundException, IOException { - final io.airbyte.api.model.generated.Notification apiNotification = generateApiNotification(); - apiNotification.getSlackConfiguration().webhook(UPDATED); - final WorkspaceUpdate workspaceUpdate = new WorkspaceUpdate() - .workspaceId(workspace.getWorkspaceId()) - .anonymousDataCollection(true) - .securityUpdates(false) - .news(false) - .initialSetupComplete(true) - .displaySetupWizard(false) - .notifications(List.of(apiNotification)) - .defaultGeography(GEOGRAPHY_US) - .webhookConfigs(List.of(new WebhookConfigWrite().name(TEST_NAME).authToken("test-auth-token"))); - - final Notification expectedNotification = generateNotification(); - expectedNotification.getSlackConfiguration().withWebhook(UPDATED); - final StandardWorkspace expectedWorkspace = new StandardWorkspace() - .withWorkspaceId(workspace.getWorkspaceId()) - .withCustomerId(workspace.getCustomerId()) - .withEmail(TEST_EMAIL) - .withName(TEST_WORKSPACE_NAME) - .withSlug(TEST_WORKSPACE_SLUG) - .withAnonymousDataCollection(true) - .withSecurityUpdates(false) - .withNews(false) - .withInitialSetupComplete(true) - .withDisplaySetupWizard(false) - .withTombstone(false) - .withNotifications(List.of(expectedNotification)) - .withDefaultGeography(Geography.US) - .withWebhookOperationConfigs(PERSISTED_WEBHOOK_CONFIGS); - - when(uuidSupplier.get()).thenReturn(WEBHOOK_CONFIG_ID); - - when(configRepository.getStandardWorkspaceNoSecrets(workspace.getWorkspaceId(), false)) - .thenReturn(workspace) - .thenReturn(expectedWorkspace); - - final WorkspaceRead actualWorkspaceRead = workspacesHandler.updateWorkspace(workspaceUpdate); - - final io.airbyte.api.model.generated.Notification expectedNotificationRead = generateApiNotification(); - expectedNotificationRead.getSlackConfiguration().webhook(UPDATED); - final WorkspaceRead expectedWorkspaceRead = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(TEST_EMAIL) - .name(TEST_WORKSPACE_NAME) - .slug(TEST_WORKSPACE_SLUG) - .initialSetupComplete(true) - .displaySetupWizard(false) - .news(false) - .anonymousDataCollection(true) - .securityUpdates(false) - .notifications(List.of(expectedNotificationRead)) - .defaultGeography(GEOGRAPHY_US) - .webhookConfigs(List.of(new WebhookConfigRead().name(TEST_NAME).id(WEBHOOK_CONFIG_ID))); - - verify(configRepository).writeStandardWorkspaceNoSecrets(expectedWorkspace); - - assertEquals(expectedWorkspaceRead, actualWorkspaceRead); - } - - @Test - void testUpdateWorkspaceWithoutWebhookConfigs() throws JsonValidationException, ConfigNotFoundException, IOException { - final io.airbyte.api.model.generated.Notification apiNotification = generateApiNotification(); - apiNotification.getSlackConfiguration().webhook(UPDATED); - final WorkspaceUpdate workspaceUpdate = new WorkspaceUpdate() - .workspaceId(workspace.getWorkspaceId()) - .anonymousDataCollection(false); - - final Notification expectedNotification = generateNotification(); - expectedNotification.getSlackConfiguration().withWebhook(UPDATED); - final StandardWorkspace expectedWorkspace = new StandardWorkspace() - .withWorkspaceId(workspace.getWorkspaceId()) - .withCustomerId(workspace.getCustomerId()) - .withEmail(TEST_EMAIL) - .withName(TEST_WORKSPACE_NAME) - .withSlug(TEST_WORKSPACE_SLUG) - .withAnonymousDataCollection(true) - .withSecurityUpdates(false) - .withNews(false) - .withInitialSetupComplete(true) - .withDisplaySetupWizard(false) - .withTombstone(false) - .withNotifications(List.of(expectedNotification)) - .withDefaultGeography(Geography.US) - .withWebhookOperationConfigs(PERSISTED_WEBHOOK_CONFIGS); - - when(uuidSupplier.get()).thenReturn(WEBHOOK_CONFIG_ID); - - when(configRepository.getStandardWorkspaceNoSecrets(workspace.getWorkspaceId(), false)) - .thenReturn(expectedWorkspace) - .thenReturn(expectedWorkspace.withAnonymousDataCollection(false)); - - workspacesHandler.updateWorkspace(workspaceUpdate); - - verify(configRepository).writeStandardWorkspaceNoSecrets(expectedWorkspace); - } - - @Test - @DisplayName("Updating workspace name should update name and slug") - void testUpdateWorkspaceNoNameUpdate() throws JsonValidationException, ConfigNotFoundException, IOException { - final WorkspaceUpdateName workspaceUpdate = new WorkspaceUpdateName() - .workspaceId(workspace.getWorkspaceId()) - .name("New Workspace Name"); - - final StandardWorkspace expectedWorkspace = new StandardWorkspace() - .withWorkspaceId(workspace.getWorkspaceId()) - .withCustomerId(workspace.getCustomerId()) - .withEmail(TEST_EMAIL) - .withName("New Workspace Name") - .withSlug("new-workspace-name") - .withAnonymousDataCollection(workspace.getAnonymousDataCollection()) - .withSecurityUpdates(workspace.getSecurityUpdates()) - .withNews(workspace.getNews()) - .withInitialSetupComplete(workspace.getInitialSetupComplete()) - .withDisplaySetupWizard(workspace.getDisplaySetupWizard()) - .withTombstone(false) - .withNotifications(workspace.getNotifications()) - .withDefaultGeography(Geography.AUTO); - - when(configRepository.getStandardWorkspaceNoSecrets(workspace.getWorkspaceId(), false)) - .thenReturn(workspace) - .thenReturn(expectedWorkspace); - - final WorkspaceRead actualWorkspaceRead = workspacesHandler.updateWorkspaceName(workspaceUpdate); - - final WorkspaceRead expectedWorkspaceRead = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(TEST_EMAIL) - .name("New Workspace Name") - .slug("new-workspace-name") - .initialSetupComplete(workspace.getInitialSetupComplete()) - .displaySetupWizard(workspace.getDisplaySetupWizard()) - .news(workspace.getNews()) - .anonymousDataCollection(workspace.getAnonymousDataCollection()) - .securityUpdates(workspace.getSecurityUpdates()) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_AUTO); - - verify(configRepository).writeStandardWorkspaceNoSecrets(expectedWorkspace); - - assertEquals(expectedWorkspaceRead, actualWorkspaceRead); - } - - @Test - @DisplayName("Partial patch update should preserve unchanged fields") - void testWorkspacePatchUpdate() throws JsonValidationException, ConfigNotFoundException, IOException { - final String EXPECTED_NEW_EMAIL = "expected-new-email@example.com"; - final WorkspaceUpdate workspaceUpdate = new WorkspaceUpdate() - .workspaceId(workspace.getWorkspaceId()) - .anonymousDataCollection(true) - .email(EXPECTED_NEW_EMAIL); - - final StandardWorkspace expectedWorkspace = Jsons.clone(workspace).withEmail(EXPECTED_NEW_EMAIL).withAnonymousDataCollection(true); - when(configRepository.getStandardWorkspaceNoSecrets(workspace.getWorkspaceId(), false)) - .thenReturn(workspace) - .thenReturn(expectedWorkspace); - // The same as the original workspace, with only the email and data collection flags changed. - final WorkspaceRead expectedWorkspaceRead = new WorkspaceRead() - .workspaceId(workspace.getWorkspaceId()) - .customerId(workspace.getCustomerId()) - .email(EXPECTED_NEW_EMAIL) - .name(workspace.getName()) - .slug(workspace.getSlug()) - .initialSetupComplete(workspace.getInitialSetupComplete()) - .displaySetupWizard(workspace.getDisplaySetupWizard()) - .news(workspace.getNews()) - .anonymousDataCollection(true) - .securityUpdates(workspace.getSecurityUpdates()) - .notifications(NotificationConverter.toApiList(workspace.getNotifications())) - .defaultGeography(GEOGRAPHY_AUTO); - - final WorkspaceRead actualWorkspaceRead = workspacesHandler.updateWorkspace(workspaceUpdate); - verify(configRepository).writeStandardWorkspaceNoSecrets(expectedWorkspace); - assertEquals(expectedWorkspaceRead, actualWorkspaceRead); - } - - @Test - void testSetFeedbackDone() throws JsonValidationException, ConfigNotFoundException, IOException { - final WorkspaceGiveFeedback workspaceGiveFeedback = new WorkspaceGiveFeedback() - .workspaceId(UUID.randomUUID()); - - workspacesHandler.setFeedbackDone(workspaceGiveFeedback); - - verify(configRepository).setFeedback(workspaceGiveFeedback.getWorkspaceId()); - } - - @Test - void testWorkspaceIsWrittenThroughSecretsWriter() throws JsonValidationException, IOException { - secretsRepositoryWriter = mock(SecretsRepositoryWriter.class); - workspacesHandler = new WorkspacesHandler(configRepository, secretsRepositoryWriter, connectionsHandler, - destinationHandler, sourceHandler, uuidSupplier); - - final UUID uuid = UUID.randomUUID(); - when(uuidSupplier.get()).thenReturn(uuid); - - final WorkspaceCreate workspaceCreate = new WorkspaceCreate() - .name(NEW_WORKSPACE) - .email(TEST_EMAIL) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_US); - - final WorkspaceRead actualRead = workspacesHandler.createWorkspace(workspaceCreate); - final WorkspaceRead expectedRead = new WorkspaceRead() - .workspaceId(uuid) - .customerId(uuid) - .email(TEST_EMAIL) - .name(NEW_WORKSPACE) - .slug("new-workspace") - .initialSetupComplete(false) - .displaySetupWizard(false) - .news(false) - .anonymousDataCollection(false) - .securityUpdates(false) - .notifications(List.of(generateApiNotification())) - .defaultGeography(GEOGRAPHY_US) - .webhookConfigs(Collections.emptyList()); - - assertEquals(expectedRead, actualRead); - verify(secretsRepositoryWriter, times(1)).writeWorkspace(any()); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/helper/OAuthPathExtractorTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/helper/OAuthPathExtractorTest.java deleted file mode 100644 index 4caeb44a65b78..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/handlers/helper/OAuthPathExtractorTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.handlers.helper; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.handlers.helpers.OAuthPathExtractor; -import java.util.List; -import java.util.Map; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; - -class OAuthPathExtractorTest { - - @Test - void testExtract() { - final JsonNode input = Jsons.deserialize(""" - { - "type": "object", - "additionalProperties": false, - "properties": { - "tenant_id": { - "type": "string", - "path_in_connector_config": ["tenant_id"] - }, - "another_property": { - "type": "string", - "path_in_connector_config": ["another", "property"] - } - } - } - """); - - final Map> expected = Map.ofEntries( - Map.entry("tenant_id", List.of("tenant_id")), - Map.entry("another_property", List.of("another", "property"))); - - Assertions.assertThat(OAuthPathExtractor.extractOauthConfigurationPaths(input)) - .containsExactlyInAnyOrderEntriesOf(expected); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectionHelpers.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectionHelpers.java deleted file mode 100644 index b509e569dafff..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectionHelpers.java +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.helpers; - -import static io.airbyte.commons.server.handlers.helpers.CatalogConverter.toApi; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.Lists; -import io.airbyte.api.model.generated.AirbyteCatalog; -import io.airbyte.api.model.generated.AirbyteStream; -import io.airbyte.api.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.model.generated.AirbyteStreamConfiguration; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionSchedule; -import io.airbyte.api.model.generated.ConnectionSchedule.TimeUnitEnum; -import io.airbyte.api.model.generated.ConnectionScheduleData; -import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; -import io.airbyte.api.model.generated.ConnectionScheduleType; -import io.airbyte.api.model.generated.ConnectionStatus; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationSnippetRead; -import io.airbyte.api.model.generated.Geography; -import io.airbyte.api.model.generated.JobStatus; -import io.airbyte.api.model.generated.ResourceRequirements; -import io.airbyte.api.model.generated.SchemaChange; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceSnippetRead; -import io.airbyte.api.model.generated.SyncMode; -import io.airbyte.api.model.generated.WebBackendConnectionListItem; -import io.airbyte.commons.enums.Enums; -import io.airbyte.commons.server.converters.ApiPojoConverters; -import io.airbyte.commons.text.Names; -import io.airbyte.config.BasicSchedule; -import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; -import io.airbyte.config.Schedule; -import io.airbyte.config.Schedule.TimeUnit; -import io.airbyte.config.ScheduleData; -import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.Status; -import io.airbyte.protocol.models.CatalogHelpers; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.protocol.models.ConfiguredAirbyteStream; -import io.airbyte.protocol.models.DestinationSyncMode; -import io.airbyte.protocol.models.Field; -import io.airbyte.protocol.models.JsonSchemaType; -import io.airbyte.protocol.models.StreamDescriptor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -public class ConnectionHelpers { - - private static final String STREAM_NAME_BASE = "users-data"; - private static final String STREAM_NAME = STREAM_NAME_BASE + "0"; - public static final String FIELD_NAME = "id"; - - public static final String SECOND_FIELD_NAME = "id2"; - private static final String BASIC_SCHEDULE_TIME_UNIT = "days"; - private static final long BASIC_SCHEDULE_UNITS = 1L; - private static final String BASIC_SCHEDULE_DATA_TIME_UNITS = "days"; - private static final long BASIC_SCHEDULE_DATA_UNITS = 1L; - private static final String ONE_HUNDRED_G = "100g"; - private static final String STANDARD_SYNC_NAME = "presto to hudi"; - private static final String STANDARD_SYNC_PREFIX = "presto_to_hudi"; - - public static final StreamDescriptor STREAM_DESCRIPTOR = new StreamDescriptor().withName(STREAM_NAME); - - // only intended for unit tests, so intentionally set very high to ensure they aren't being used - // elsewhere - public static final io.airbyte.config.ResourceRequirements TESTING_RESOURCE_REQUIREMENTS = new io.airbyte.config.ResourceRequirements() - .withCpuLimit(ONE_HUNDRED_G) - .withCpuRequest(ONE_HUNDRED_G) - .withMemoryLimit(ONE_HUNDRED_G) - .withMemoryRequest(ONE_HUNDRED_G); - - public static StandardSync generateSyncWithSourceId(final UUID sourceId) { - final UUID connectionId = UUID.randomUUID(); - - return new StandardSync() - .withConnectionId(connectionId) - .withName(STANDARD_SYNC_NAME) - .withNamespaceDefinition(NamespaceDefinitionType.SOURCE) - .withNamespaceFormat(null) - .withPrefix(STANDARD_SYNC_PREFIX) - .withStatus(StandardSync.Status.ACTIVE) - .withCatalog(generateBasicConfiguredAirbyteCatalog()) - .withSourceId(sourceId) - .withDestinationId(UUID.randomUUID()) - .withOperationIds(List.of(UUID.randomUUID())) - .withManual(false) - .withSchedule(generateBasicSchedule()) - .withResourceRequirements(TESTING_RESOURCE_REQUIREMENTS) - .withBreakingChange(false); - } - - public static StandardSync generateSyncWithDestinationId(final UUID destinationId) { - final UUID connectionId = UUID.randomUUID(); - - return new StandardSync() - .withConnectionId(connectionId) - .withName(STANDARD_SYNC_NAME) - .withNamespaceDefinition(NamespaceDefinitionType.SOURCE) - .withNamespaceFormat(null) - .withPrefix(STANDARD_SYNC_PREFIX) - .withStatus(StandardSync.Status.ACTIVE) - .withCatalog(generateBasicConfiguredAirbyteCatalog()) - .withSourceId(UUID.randomUUID()) - .withDestinationId(destinationId) - .withOperationIds(List.of(UUID.randomUUID())) - .withManual(true); - } - - public static StandardSync generateSyncWithSourceAndDestinationId(final UUID sourceId, - final UUID destinationId, - final boolean isBroken, - final Status status) { - final UUID connectionId = UUID.randomUUID(); - - return new StandardSync() - .withConnectionId(connectionId) - .withName(STANDARD_SYNC_NAME) - .withNamespaceDefinition(NamespaceDefinitionType.SOURCE) - .withNamespaceFormat(null) - .withPrefix(STANDARD_SYNC_PREFIX) - .withStatus(status) - .withCatalog(generateBasicConfiguredAirbyteCatalog()) - .withSourceCatalogId(UUID.randomUUID()) - .withSourceId(sourceId) - .withDestinationId(destinationId) - .withOperationIds(List.of(UUID.randomUUID())) - .withManual(true) - .withBreakingChange(isBroken); - } - - public static ConnectionSchedule generateBasicConnectionSchedule() { - return new ConnectionSchedule() - .timeUnit(ConnectionSchedule.TimeUnitEnum.fromValue(BASIC_SCHEDULE_TIME_UNIT)) - .units(BASIC_SCHEDULE_UNITS); - } - - public static Schedule generateBasicSchedule() { - return new Schedule() - .withTimeUnit(TimeUnit.fromValue(BASIC_SCHEDULE_TIME_UNIT)) - .withUnits(BASIC_SCHEDULE_UNITS); - } - - public static ConnectionScheduleData generateBasicConnectionScheduleData() { - return new ConnectionScheduleData().basicSchedule( - new ConnectionScheduleDataBasicSchedule().timeUnit(ConnectionScheduleDataBasicSchedule.TimeUnitEnum.DAYS).units(BASIC_SCHEDULE_UNITS)); - } - - public static ScheduleData generateBasicScheduleData() { - return new ScheduleData().withBasicSchedule(new BasicSchedule() - .withTimeUnit(BasicSchedule.TimeUnit.fromValue((BASIC_SCHEDULE_DATA_TIME_UNITS))) - .withUnits(BASIC_SCHEDULE_DATA_UNITS)); - } - - public static ConnectionRead generateExpectedConnectionRead(final UUID connectionId, - final UUID sourceId, - final UUID destinationId, - final List operationIds, - final UUID sourceCatalogId, - final Geography geography, - final boolean breaking) { - - return new ConnectionRead() - .connectionId(connectionId) - .sourceId(sourceId) - .destinationId(destinationId) - .operationIds(operationIds) - .name("presto to hudi") - .namespaceDefinition(io.airbyte.api.model.generated.NamespaceDefinitionType.SOURCE) - .namespaceFormat(null) - .prefix("presto_to_hudi") - .schedule(generateBasicConnectionSchedule()) - .scheduleType(ConnectionScheduleType.BASIC) - .scheduleData(generateBasicConnectionScheduleData()) - .syncCatalog(ConnectionHelpers.generateBasicApiCatalog()) - .resourceRequirements(new ResourceRequirements() - .cpuRequest(TESTING_RESOURCE_REQUIREMENTS.getCpuRequest()) - .cpuLimit(TESTING_RESOURCE_REQUIREMENTS.getCpuLimit()) - .memoryRequest(TESTING_RESOURCE_REQUIREMENTS.getMemoryRequest()) - .memoryLimit(TESTING_RESOURCE_REQUIREMENTS.getMemoryLimit())) - .sourceCatalogId(sourceCatalogId) - .geography(geography) - .breakingChange(breaking); - } - - public static ConnectionRead generateExpectedConnectionRead(final StandardSync standardSync) { - final ConnectionRead connectionRead = generateExpectedConnectionRead( - standardSync.getConnectionId(), - standardSync.getSourceId(), - standardSync.getDestinationId(), - standardSync.getOperationIds(), - standardSync.getSourceCatalogId(), - Enums.convertTo(standardSync.getGeography(), Geography.class), - standardSync.getBreakingChange()); - - if (standardSync.getSchedule() == null) { - connectionRead.schedule(null); - } else { - connectionRead.schedule(new ConnectionSchedule() - .timeUnit(TimeUnitEnum.fromValue(standardSync.getSchedule().getTimeUnit().value())) - .units(standardSync.getSchedule().getUnits())); - } - - if (standardSync.getStatus() == Status.INACTIVE) { - connectionRead.setStatus(ConnectionStatus.INACTIVE); - } else if (standardSync.getStatus() == Status.ACTIVE) { - connectionRead.setStatus(ConnectionStatus.ACTIVE); - } else if (standardSync.getStatus() == Status.DEPRECATED) { - connectionRead.setStatus(ConnectionStatus.DEPRECATED); - } - - return connectionRead; - } - - public static ConnectionRead connectionReadFromStandardSync(final StandardSync standardSync) { - final ConnectionRead connectionRead = new ConnectionRead(); - connectionRead - .connectionId(standardSync.getConnectionId()) - .sourceId(standardSync.getSourceId()) - .destinationId(standardSync.getDestinationId()) - .operationIds(standardSync.getOperationIds()) - .name(standardSync.getName()) - .namespaceFormat(standardSync.getNamespaceFormat()) - .prefix(standardSync.getPrefix()) - .sourceCatalogId(standardSync.getSourceCatalogId()) - .geography(ApiPojoConverters.toApiGeography(standardSync.getGeography())) - .breakingChange(standardSync.getBreakingChange()); - - if (standardSync.getNamespaceDefinition() != null) { - connectionRead - .namespaceDefinition(io.airbyte.api.model.generated.NamespaceDefinitionType.fromValue(standardSync.getNamespaceDefinition().value())); - } - if (standardSync.getStatus() != null) { - connectionRead.status(io.airbyte.api.model.generated.ConnectionStatus.fromValue(standardSync.getStatus().value())); - } - ApiPojoConverters.populateConnectionReadSchedule(standardSync, connectionRead); - - if (standardSync.getCatalog() != null) { - connectionRead.syncCatalog(toApi(standardSync.getCatalog(), standardSync.getFieldSelectionData())); - } - if (standardSync.getResourceRequirements() != null) { - connectionRead.resourceRequirements(new io.airbyte.api.model.generated.ResourceRequirements() - .cpuLimit(standardSync.getResourceRequirements().getCpuLimit()) - .cpuRequest(standardSync.getResourceRequirements().getCpuRequest()) - .memoryLimit(standardSync.getResourceRequirements().getMemoryLimit()) - .memoryRequest(standardSync.getResourceRequirements().getMemoryRequest())); - } - return connectionRead; - } - - public static WebBackendConnectionListItem generateExpectedWebBackendConnectionListItem( - final StandardSync standardSync, - final SourceRead source, - final DestinationRead destination, - final boolean isSyncing, - final Long latestSyncJobCreatedAt, - final JobStatus latestSynJobStatus, - final SchemaChange schemaChange) { - - final WebBackendConnectionListItem connectionListItem = new WebBackendConnectionListItem() - .connectionId(standardSync.getConnectionId()) - .name(standardSync.getName()) - .source(new SourceSnippetRead() - .icon(source.getIcon()) - .name(source.getName()) - .sourceName(source.getSourceName()) - .sourceDefinitionId(source.getSourceDefinitionId()) - .sourceId(source.getSourceId())) - .destination(new DestinationSnippetRead() - .icon(destination.getIcon()) - .name(destination.getName()) - .destinationName(destination.getDestinationName()) - .destinationDefinitionId(destination.getDestinationDefinitionId()) - .destinationId(destination.getDestinationId())) - .status(ApiPojoConverters.toApiStatus(standardSync.getStatus())) - .isSyncing(isSyncing) - .latestSyncJobCreatedAt(latestSyncJobCreatedAt) - .latestSyncJobStatus(latestSynJobStatus) - .scheduleType(ApiPojoConverters.toApiConnectionScheduleType(standardSync)) - .scheduleData(ApiPojoConverters.toApiConnectionScheduleData(standardSync)) - .schemaChange(schemaChange); - - return connectionListItem; - } - - public static JsonNode generateBasicJsonSchema() { - return CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD_NAME, JsonSchemaType.STRING)); - } - - public static JsonNode generateJsonSchemaWithTwoFields() { - return CatalogHelpers.fieldsToJsonSchema( - Field.of(FIELD_NAME, JsonSchemaType.STRING), - Field.of(SECOND_FIELD_NAME, JsonSchemaType.STRING)); - } - - public static ConfiguredAirbyteCatalog generateBasicConfiguredAirbyteCatalog() { - return new ConfiguredAirbyteCatalog().withStreams(Collections.singletonList(generateBasicConfiguredStream(null))); - } - - public static ConfiguredAirbyteCatalog generateAirbyteCatalogWithTwoFields() { - return new ConfiguredAirbyteCatalog().withStreams(Collections.singletonList(new ConfiguredAirbyteStream() - .withStream( - new io.airbyte.protocol.models.AirbyteStream() - .withName(STREAM_NAME) - .withJsonSchema(generateJsonSchemaWithTwoFields()) - .withDefaultCursorField(Lists.newArrayList(FIELD_NAME)) - .withSourceDefinedCursor(false) - .withSourceDefinedPrimaryKey(Collections.emptyList()) - .withSupportedSyncModes( - List.of(io.airbyte.protocol.models.SyncMode.FULL_REFRESH, io.airbyte.protocol.models.SyncMode.INCREMENTAL))))); - } - - public static ConfiguredAirbyteCatalog generateMultipleStreamsConfiguredAirbyteCatalog(final int streamsCount) { - final List configuredStreams = new ArrayList<>(); - for (int i = 0; i < streamsCount; i++) { - configuredStreams.add(generateBasicConfiguredStream(String.valueOf(i))); - } - return new ConfiguredAirbyteCatalog().withStreams(configuredStreams); - } - - public static ConfiguredAirbyteStream generateBasicConfiguredStream(final String nameSuffix) { - return new ConfiguredAirbyteStream() - .withStream(generateBasicAirbyteStream(nameSuffix)) - .withCursorField(Lists.newArrayList(FIELD_NAME)) - .withSyncMode(io.airbyte.protocol.models.SyncMode.INCREMENTAL) - .withDestinationSyncMode(DestinationSyncMode.APPEND); - } - - private static io.airbyte.protocol.models.AirbyteStream generateBasicAirbyteStream(final String nameSuffix) { - return CatalogHelpers.createAirbyteStream( - nameSuffix == null ? STREAM_NAME : STREAM_NAME_BASE + nameSuffix, Field.of(FIELD_NAME, JsonSchemaType.STRING)) - .withDefaultCursorField(Lists.newArrayList(FIELD_NAME)) - .withSourceDefinedCursor(false) - .withSupportedSyncModes(List.of(io.airbyte.protocol.models.SyncMode.FULL_REFRESH, io.airbyte.protocol.models.SyncMode.INCREMENTAL)); - } - - public static AirbyteCatalog generateBasicApiCatalog() { - return new AirbyteCatalog().streams(Lists.newArrayList(new AirbyteStreamAndConfiguration() - .stream(generateBasicApiStream(null)) - .config(generateBasicApiStreamConfig(null)))); - } - - /** - * Generates an API catalog that has two fields, both selected. - * - * @return AirbyteCatalog - */ - public static AirbyteCatalog generateApiCatalogWithTwoFields() { - return new AirbyteCatalog().streams(Lists.newArrayList(new AirbyteStreamAndConfiguration() - .stream(generateApiStreamWithTwoFields()) - .config(generateBasicApiStreamConfig(null)))); - } - - public static AirbyteCatalog generateMultipleStreamsApiCatalog(final int streamsCount) { - final List streamAndConfigurations = new ArrayList<>(); - for (int i = 0; i < streamsCount; i++) { - streamAndConfigurations.add(new AirbyteStreamAndConfiguration() - .stream(generateBasicApiStream(String.valueOf(i))) - .config(generateBasicApiStreamConfig(String.valueOf(i)))); - } - return new AirbyteCatalog().streams(streamAndConfigurations); - } - - private static AirbyteStreamConfiguration generateBasicApiStreamConfig(final String nameSuffix) { - return new AirbyteStreamConfiguration() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(Lists.newArrayList(FIELD_NAME)) - .destinationSyncMode(io.airbyte.api.model.generated.DestinationSyncMode.APPEND) - .primaryKey(Collections.emptyList()) - .aliasName(Names.toAlphanumericAndUnderscore(nameSuffix == null ? STREAM_NAME : STREAM_NAME_BASE + nameSuffix)) - .selected(true) - .fieldSelectionEnabled(false); - } - - private static AirbyteStream generateBasicApiStream(final String nameSuffix) { - return new AirbyteStream() - .name(nameSuffix == null ? STREAM_NAME : STREAM_NAME_BASE + nameSuffix) - .jsonSchema(generateBasicJsonSchema()) - .defaultCursorField(Lists.newArrayList(FIELD_NAME)) - .sourceDefinedCursor(false) - .sourceDefinedPrimaryKey(Collections.emptyList()) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - } - - private static AirbyteStream generateApiStreamWithTwoFields() { - return new AirbyteStream() - .name(STREAM_NAME) - .jsonSchema(generateJsonSchemaWithTwoFields()) - .defaultCursorField(Lists.newArrayList(FIELD_NAME)) - .sourceDefinedCursor(false) - .sourceDefinedPrimaryKey(Collections.emptyList()) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectorSpecificationHelpers.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectorSpecificationHelpers.java deleted file mode 100644 index 2997705ae42b7..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/ConnectorSpecificationHelpers.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.helpers; - -import io.airbyte.commons.json.Jsons; -import io.airbyte.protocol.models.ConnectorSpecification; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class ConnectorSpecificationHelpers { - - public static ConnectorSpecification generateConnectorSpecification() throws IOException { - - final Path path = Paths.get(ConnectorSpecificationHelpers.class.getClassLoader().getResource("json/TestSpecification.json").getPath()); - - try { - return new ConnectorSpecification() - .withDocumentationUrl(new URI("https://airbyte.io")) - .withConnectionSpecification(Jsons.deserialize(Files.readString(path))) - .withSupportsDBT(false) - .withSupportsNormalization(false); - } catch (final URISyntaxException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationDefinitionHelpers.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationDefinitionHelpers.java deleted file mode 100644 index eb23997843a4a..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationDefinitionHelpers.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.helpers; - -import io.airbyte.config.StandardDestinationDefinition; -import java.util.UUID; - -public class DestinationDefinitionHelpers { - - public static StandardDestinationDefinition generateDestination() { - return new StandardDestinationDefinition() - .withDestinationDefinitionId(UUID.randomUUID()) - .withName("db2") - .withDockerRepository("thebestrepo") - .withDockerImageTag("thelatesttag") - .withDocumentationUrl("https://wikipedia.org"); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationHelpers.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationHelpers.java deleted file mode 100644 index 5a49af66e279e..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/DestinationHelpers.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.helpers; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.handlers.DestinationDefinitionsHandler; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.StandardDestinationDefinition; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.UUID; - -public class DestinationHelpers { - - public static JsonNode getTestDestinationJson() throws IOException { - final Path path = - Paths.get(DestinationHelpers.class.getClassLoader().getResource("json/TestImplementation.json").getPath()); - - return Jsons.deserialize(Files.readString(path)); - } - - public static DestinationConnection generateDestination(final UUID destinationDefinitionId) throws IOException { - return generateDestination(destinationDefinitionId, "my default dest name", false); - } - - public static DestinationConnection generateDestination(final UUID destinationDefinitionId, final String name) throws IOException { - return generateDestination(destinationDefinitionId, name, false); - } - - public static DestinationConnection generateDestination(final UUID destinationDefinitionId, final boolean tombstone) throws IOException { - return generateDestination(destinationDefinitionId, "my default dest name", tombstone); - } - - public static DestinationConnection generateDestination(final UUID destinationDefinitionId, final String name, final boolean tombstone) - throws IOException { - final UUID workspaceId = UUID.randomUUID(); - final UUID destinationId = UUID.randomUUID(); - - final JsonNode implementationJson = getTestDestinationJson(); - - return new DestinationConnection() - .withName(name) - .withWorkspaceId(workspaceId) - .withDestinationDefinitionId(destinationDefinitionId) - .withDestinationId(destinationId) - .withConfiguration(implementationJson) - .withTombstone(tombstone); - } - - public static DestinationRead getDestinationRead(final DestinationConnection destination, - final StandardDestinationDefinition standardDestinationDefinition) { - return new DestinationRead() - .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) - .workspaceId(destination.getWorkspaceId()) - .destinationDefinitionId(destination.getDestinationDefinitionId()) - .destinationId(destination.getDestinationId()) - .connectionConfiguration(destination.getConfiguration()) - .name(destination.getName()) - .destinationName(standardDestinationDefinition.getName()) - .icon(DestinationDefinitionsHandler.loadIcon(standardDestinationDefinition.getIcon())); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceDefinitionHelpers.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceDefinitionHelpers.java deleted file mode 100644 index d76d0726e822e..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceDefinitionHelpers.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.helpers; - -import io.airbyte.config.StandardSourceDefinition; -import java.util.UUID; - -public class SourceDefinitionHelpers { - - public static StandardSourceDefinition generateSourceDefinition() { - return new StandardSourceDefinition() - .withSourceDefinitionId(UUID.randomUUID()) - .withName("marketo") - .withDockerRepository("thebestrepo") - .withDockerImageTag("thelatesttag") - .withDocumentationUrl("https://wikipedia.org"); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceHelpers.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceHelpers.java deleted file mode 100644 index 354e2634ea70c..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/helpers/SourceHelpers.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.helpers; - -import com.fasterxml.jackson.databind.JsonNode; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.handlers.SourceDefinitionsHandler; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardSourceDefinition; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.UUID; - -public class SourceHelpers { - - public static SourceConnection generateSource(final UUID sourceDefinitionId) throws IOException { - return generateSource(sourceDefinitionId, "my default source name", false); - } - - public static SourceConnection generateSource(final UUID sourceDefinitionId, final String name) throws IOException { - return generateSource(sourceDefinitionId, name, false); - } - - public static SourceConnection generateSource(final UUID sourceDefinitionId, final boolean tombstone) throws IOException { - return generateSource(sourceDefinitionId, "my default source name", tombstone); - } - - public static SourceConnection generateSource(final UUID sourceDefinitionId, final String name, final boolean tombstone) throws IOException { - final UUID workspaceId = UUID.randomUUID(); - final UUID sourceId = UUID.randomUUID(); - - final JsonNode implementationJson = getTestImplementationJson(); - - return new SourceConnection() - .withName(name) - .withWorkspaceId(workspaceId) - .withSourceDefinitionId(sourceDefinitionId) - .withSourceId(sourceId) - .withConfiguration(implementationJson) - .withTombstone(tombstone); - } - - public static JsonNode getTestImplementationJson() throws IOException { - final Path path = Paths.get(SourceHelpers.class.getClassLoader().getResource("json/TestImplementation.json").getPath()); - return Jsons.deserialize(Files.readString(path)); - } - - public static SourceRead getSourceRead(final SourceConnection source, final StandardSourceDefinition standardSourceDefinition) { - - return new SourceRead() - .sourceDefinitionId(standardSourceDefinition.getSourceDefinitionId()) - .workspaceId(source.getWorkspaceId()) - .sourceDefinitionId(source.getSourceDefinitionId()) - .sourceId(source.getSourceId()) - .connectionConfiguration(source.getConfiguration()) - .name(source.getName()) - .sourceName(standardSourceDefinition.getName()) - .icon(SourceDefinitionsHandler.loadIcon(standardSourceDefinition.getIcon())); - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClientTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClientTest.java deleted file mode 100644 index e25aa0dcfd362..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/scheduler/DefaultSynchronousSchedulerClientTest.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.scheduler; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.ImmutableMap; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.temporal.JobMetadata; -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.temporal.TemporalJobType; -import io.airbyte.commons.temporal.TemporalResponse; -import io.airbyte.commons.temporal.scheduling.RouterService; -import io.airbyte.commons.version.Version; -import io.airbyte.config.ActorType; -import io.airbyte.config.ConnectorJobOutput; -import io.airbyte.config.DestinationConnection; -import io.airbyte.config.JobCheckConnectionConfig; -import io.airbyte.config.JobConfig.ConfigType; -import io.airbyte.config.JobDiscoverCatalogConfig; -import io.airbyte.config.JobGetSpecConfig; -import io.airbyte.config.SourceConnection; -import io.airbyte.config.StandardCheckConnectionOutput; -import io.airbyte.persistence.job.errorreporter.ConnectorJobReportingContext; -import io.airbyte.persistence.job.errorreporter.JobErrorReporter; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.persistence.job.tracker.JobTracker; -import io.airbyte.persistence.job.tracker.JobTracker.JobState; -import io.airbyte.protocol.models.ConnectorSpecification; -import java.io.IOException; -import java.nio.file.Path; -import java.util.UUID; -import java.util.function.Function; -import java.util.function.Supplier; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -// the goal here is to test the "execute" part of this class and all of the various exceptional -// cases. then separately test submission of each job type without having to re-test all of the -// execution exception cases again. -class DefaultSynchronousSchedulerClientTest { - - private static final Path LOG_PATH = Path.of("/tmp"); - private static final String DOCKER_IMAGE = "foo/bar"; - private static final String DOCKER_IMAGE_TAG = "baz/qux"; - private static final Version PROTOCOL_VERSION = new Version("0.2.3"); - private static final UUID WORKSPACE_ID = UUID.randomUUID(); - private static final UUID UUID1 = UUID.randomUUID(); - private static final UUID UUID2 = UUID.randomUUID(); - private static final String UNCHECKED = "unchecked"; - private static final String CHECK_TASK_QUEUE = "check"; - private static final String DISCOVER_TASK_QUEUE = "discover"; - private static final JsonNode CONFIGURATION = Jsons.jsonNode(ImmutableMap.builder() - .put("username", "airbyte") - .put("password", "abc") - .build()); - private static final SourceConnection SOURCE_CONNECTION = new SourceConnection() - .withSourceId(UUID1) - .withSourceDefinitionId(UUID2) - .withConfiguration(CONFIGURATION); - private static final DestinationConnection DESTINATION_CONNECTION = new DestinationConnection() - .withDestinationId(UUID1) - .withDestinationDefinitionId(UUID2) - .withConfiguration(CONFIGURATION); - private static final String SOURCE_DOCKER_IMAGE = "source-airbyte:1.2.3"; - - private TemporalClient temporalClient; - private JobTracker jobTracker; - private JobErrorReporter jobErrorReporter; - private OAuthConfigSupplier oAuthConfigSupplier; - - private RouterService routerService; - private DefaultSynchronousSchedulerClient schedulerClient; - - @BeforeEach - void setup() throws IOException { - temporalClient = mock(TemporalClient.class); - jobTracker = mock(JobTracker.class); - jobErrorReporter = mock(JobErrorReporter.class); - oAuthConfigSupplier = mock(OAuthConfigSupplier.class); - routerService = mock(RouterService.class); - schedulerClient = new DefaultSynchronousSchedulerClient(temporalClient, jobTracker, jobErrorReporter, oAuthConfigSupplier, routerService); - - when(oAuthConfigSupplier.injectSourceOAuthParameters(any(), any(), eq(CONFIGURATION))).thenReturn(CONFIGURATION); - when(oAuthConfigSupplier.injectDestinationOAuthParameters(any(), any(), eq(CONFIGURATION))).thenReturn(CONFIGURATION); - - when(routerService.getTaskQueueForWorkspace(any(), eq(TemporalJobType.CHECK_CONNECTION))).thenReturn(CHECK_TASK_QUEUE); - when(routerService.getTaskQueueForWorkspace(any(), eq(TemporalJobType.DISCOVER_SCHEMA))).thenReturn(DISCOVER_TASK_QUEUE); - } - - private static JobMetadata createMetadata(final boolean succeeded) { - return new JobMetadata( - succeeded, - LOG_PATH); - } - - @Nested - @DisplayName("Test execute method.") - class ExecuteSynchronousJob { - - @SuppressWarnings(UNCHECKED) - @Test - void testExecuteJobSuccess() { - final UUID sourceDefinitionId = UUID.randomUUID(); - final UUID discoveredCatalogId = UUID.randomUUID(); - final Supplier> function = mock(Supplier.class); - final Function mapperFunction = ConnectorJobOutput::getDiscoverCatalogId; - final ConnectorJobOutput jobOutput = new ConnectorJobOutput().withDiscoverCatalogId(discoveredCatalogId); - when(function.get()).thenReturn(new TemporalResponse<>(jobOutput, createMetadata(true))); - - final ConnectorJobReportingContext jobContext = new ConnectorJobReportingContext(UUID.randomUUID(), SOURCE_DOCKER_IMAGE); - final SynchronousResponse response = schedulerClient - .execute(ConfigType.DISCOVER_SCHEMA, jobContext, sourceDefinitionId, function, mapperFunction, WORKSPACE_ID); - - assertNotNull(response); - assertEquals(discoveredCatalogId, response.getOutput()); - assertEquals(ConfigType.DISCOVER_SCHEMA, response.getMetadata().getConfigType()); - assertTrue(response.getMetadata().getConfigId().isPresent()); - assertEquals(sourceDefinitionId, response.getMetadata().getConfigId().get()); - assertTrue(response.getMetadata().isSucceeded()); - assertEquals(LOG_PATH, response.getMetadata().getLogPath()); - - verify(jobTracker).trackDiscover(any(UUID.class), eq(sourceDefinitionId), eq(WORKSPACE_ID), eq(JobState.STARTED)); - verify(jobTracker).trackDiscover(any(UUID.class), eq(sourceDefinitionId), eq(WORKSPACE_ID), eq(JobState.SUCCEEDED)); - verifyNoInteractions(jobErrorReporter); - } - - @SuppressWarnings(UNCHECKED) - @Test - void testExecuteJobFailure() { - final UUID sourceDefinitionId = UUID.randomUUID(); - final Supplier> function = mock(Supplier.class); - final Function mapperFunction = ConnectorJobOutput::getDiscoverCatalogId; - when(function.get()).thenReturn(new TemporalResponse<>(null, createMetadata(false))); - - final ConnectorJobReportingContext jobContext = new ConnectorJobReportingContext(UUID.randomUUID(), SOURCE_DOCKER_IMAGE); - final SynchronousResponse response = schedulerClient - .execute(ConfigType.DISCOVER_SCHEMA, jobContext, sourceDefinitionId, function, mapperFunction, WORKSPACE_ID); - - assertNotNull(response); - assertNull(response.getOutput()); - assertEquals(ConfigType.DISCOVER_SCHEMA, response.getMetadata().getConfigType()); - assertTrue(response.getMetadata().getConfigId().isPresent()); - assertEquals(sourceDefinitionId, response.getMetadata().getConfigId().get()); - assertFalse(response.getMetadata().isSucceeded()); - assertEquals(LOG_PATH, response.getMetadata().getLogPath()); - - verify(jobTracker).trackDiscover(any(UUID.class), eq(sourceDefinitionId), eq(WORKSPACE_ID), eq(JobState.STARTED)); - verify(jobTracker).trackDiscover(any(UUID.class), eq(sourceDefinitionId), eq(WORKSPACE_ID), eq(JobState.FAILED)); - verifyNoInteractions(jobErrorReporter); - } - - @SuppressWarnings(UNCHECKED) - @Test - void testExecuteRuntimeException() { - final UUID sourceDefinitionId = UUID.randomUUID(); - final Supplier> function = mock(Supplier.class); - final Function mapperFunction = ConnectorJobOutput::getDiscoverCatalogId; - when(function.get()).thenThrow(new RuntimeException()); - - final ConnectorJobReportingContext jobContext = new ConnectorJobReportingContext(UUID.randomUUID(), SOURCE_DOCKER_IMAGE); - assertThrows( - RuntimeException.class, - () -> schedulerClient.execute(ConfigType.DISCOVER_SCHEMA, jobContext, sourceDefinitionId, function, - mapperFunction, WORKSPACE_ID)); - - verify(jobTracker).trackDiscover(any(UUID.class), eq(sourceDefinitionId), eq(WORKSPACE_ID), eq(JobState.STARTED)); - verify(jobTracker).trackDiscover(any(UUID.class), eq(sourceDefinitionId), eq(WORKSPACE_ID), eq(JobState.FAILED)); - verifyNoInteractions(jobErrorReporter); - } - - } - - @Nested - @DisplayName("Test job creation for each configuration type.") - class TestJobCreation { - - @Test - void testCreateSourceCheckConnectionJob() throws IOException { - final JobCheckConnectionConfig jobCheckConnectionConfig = new JobCheckConnectionConfig() - .withActorType(ActorType.SOURCE) - .withActorId(SOURCE_CONNECTION.getSourceId()) - .withConnectionConfiguration(SOURCE_CONNECTION.getConfiguration()) - .withDockerImage(DOCKER_IMAGE) - .withProtocolVersion(PROTOCOL_VERSION).withIsCustomConnector(false); - - final StandardCheckConnectionOutput mockOutput = mock(StandardCheckConnectionOutput.class); - final ConnectorJobOutput jobOutput = new ConnectorJobOutput().withCheckConnection(mockOutput); - when(temporalClient.submitCheckConnection(any(UUID.class), eq(0), eq(CHECK_TASK_QUEUE), eq(jobCheckConnectionConfig))) - .thenReturn(new TemporalResponse<>(jobOutput, createMetadata(true))); - final SynchronousResponse response = - schedulerClient.createSourceCheckConnectionJob(SOURCE_CONNECTION, DOCKER_IMAGE, PROTOCOL_VERSION, false); - assertEquals(mockOutput, response.getOutput()); - } - - @Test - void testCreateDestinationCheckConnectionJob() throws IOException { - final JobCheckConnectionConfig jobCheckConnectionConfig = new JobCheckConnectionConfig() - .withActorType(ActorType.DESTINATION) - .withActorId(DESTINATION_CONNECTION.getDestinationId()) - .withConnectionConfiguration(DESTINATION_CONNECTION.getConfiguration()) - .withDockerImage(DOCKER_IMAGE) - .withProtocolVersion(PROTOCOL_VERSION) - .withIsCustomConnector(false); - - final StandardCheckConnectionOutput mockOutput = mock(StandardCheckConnectionOutput.class); - final ConnectorJobOutput jobOutput = new ConnectorJobOutput().withCheckConnection(mockOutput); - when(temporalClient.submitCheckConnection(any(UUID.class), eq(0), eq(CHECK_TASK_QUEUE), eq(jobCheckConnectionConfig))) - .thenReturn(new TemporalResponse<>(jobOutput, createMetadata(true))); - final SynchronousResponse response = - schedulerClient.createDestinationCheckConnectionJob(DESTINATION_CONNECTION, DOCKER_IMAGE, PROTOCOL_VERSION, false); - assertEquals(mockOutput, response.getOutput()); - } - - @Test - void testCreateDiscoverSchemaJob() throws IOException { - final UUID expectedCatalogId = UUID.randomUUID(); - final ConnectorJobOutput jobOutput = new ConnectorJobOutput().withDiscoverCatalogId(expectedCatalogId); - when(temporalClient.submitDiscoverSchema(any(UUID.class), eq(0), eq(DISCOVER_TASK_QUEUE), any(JobDiscoverCatalogConfig.class))) - .thenReturn(new TemporalResponse<>(jobOutput, createMetadata(true))); - final SynchronousResponse response = - schedulerClient.createDiscoverSchemaJob(SOURCE_CONNECTION, DOCKER_IMAGE, DOCKER_IMAGE_TAG, PROTOCOL_VERSION, false); - assertEquals(expectedCatalogId, response.getOutput()); - } - - @Test - void testCreateGetSpecJob() throws IOException { - final JobGetSpecConfig jobSpecConfig = new JobGetSpecConfig().withDockerImage(DOCKER_IMAGE).withIsCustomConnector(false); - - final ConnectorSpecification mockOutput = mock(ConnectorSpecification.class); - final ConnectorJobOutput jobOutput = new ConnectorJobOutput().withSpec(mockOutput); - when(temporalClient.submitGetSpec(any(UUID.class), eq(0), eq(jobSpecConfig))) - .thenReturn(new TemporalResponse<>(jobOutput, createMetadata(true))); - final SynchronousResponse response = schedulerClient.createGetSpecJob(DOCKER_IMAGE, false); - assertEquals(mockOutput, response.getOutput()); - } - - } - -} diff --git a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/services/AirbyteGithubStoreTest.java b/airbyte-commons-server/src/test/java/io/airbyte/commons/server/services/AirbyteGithubStoreTest.java deleted file mode 100644 index 414fdabd37170..0000000000000 --- a/airbyte-commons-server/src/test/java/io/airbyte/commons/server/services/AirbyteGithubStoreTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.commons.server.services; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.io.IOException; -import java.net.http.HttpTimeoutException; -import java.time.Duration; -import java.util.Collections; -import java.util.concurrent.TimeUnit; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -public class AirbyteGithubStoreTest { - - private static final Duration TIMEOUT = Duration.ofSeconds(1); - private static final String CONTENT_TYPE = "Content-Type"; - private static final String PLAIN_TEXT = "text/plain; charset=utf-8"; - private static final String CACHE_CONTROL = "Cache-Control"; - private static final String NO_CACHE = "no-cache"; - - private MockWebServer webServer; - private AirbyteGithubStore githubStore; - - @BeforeEach - public void setUp() { - webServer = new MockWebServer(); - githubStore = AirbyteGithubStore.test(webServer.url("/").toString(), TIMEOUT); - } - - @Nested - @DisplayName("when the additional definitions file is unusable, badly formatted, or cannot be retrieved due to errors") - class FileUnusable { - - @Test - void testGetLatestSourcesWithNonJson() throws InterruptedException { - final var nonjsonBody = "irrelevant text"; - final var nonjsonResponse = new MockResponse().setResponseCode(200) - .addHeader(CONTENT_TYPE, PLAIN_TEXT) - .addHeader(CACHE_CONTROL, NO_CACHE) - .setBody(nonjsonBody); - webServer.enqueue(nonjsonResponse); - assertEquals(Collections.emptyList(), githubStore.getLatestSources()); - } - - @Test - void testGetLatestSourcesWithWrongSchemaJson() throws InterruptedException { - final var jsonBody = "{ json: 'validButWrongFormat' }"; - final var jsonResponse = new MockResponse().setResponseCode(200) - .addHeader(CONTENT_TYPE, "application/json; charset=utf-8") - .addHeader(CACHE_CONTROL, NO_CACHE) - .setBody(jsonBody); - webServer.enqueue(jsonResponse); - assertEquals(Collections.emptyList(), githubStore.getLatestSources()); - } - - @Test - void testGetLatestDestinationsWithNonJson() throws InterruptedException { - final var nonjsonBody = "irrelevant text"; - final var nonjsonResponse = new MockResponse().setResponseCode(200) - .addHeader(CONTENT_TYPE, PLAIN_TEXT) - .addHeader(CACHE_CONTROL, NO_CACHE) - .setBody(nonjsonBody); - webServer.enqueue(nonjsonResponse); - assertEquals(Collections.emptyList(), githubStore.getLatestDestinations()); - } - - @Test - void testGetLatestDestinationsWithWrongSchemaJson() throws InterruptedException { - final var jsonBody = "{ json: 'validButWrongFormat' }"; - final var jsonResponse = new MockResponse().setResponseCode(200) - .addHeader(CONTENT_TYPE, "application/json; charset=utf-8") - .addHeader(CACHE_CONTROL, NO_CACHE) - .setBody(jsonBody); - webServer.enqueue(jsonResponse); - assertEquals(Collections.emptyList(), githubStore.getLatestDestinations()); - } - - } - - @Nested - @DisplayName("when there is no internet") - class NoInternet { - - @Test - void testGetLatestDestinations() throws InterruptedException, IOException { - webServer.shutdown(); - assertEquals(Collections.emptyList(), githubStore.getLatestDestinations()); - } - - @Test - void testGetLatestSources() throws InterruptedException, IOException { - webServer.shutdown(); - assertEquals(Collections.emptyList(), githubStore.getLatestSources()); - } - - } - - @Nested - @DisplayName("when a bad file is specified") - class BadFile { - - @Test - void testGetLatestDestinations() throws InterruptedException { - final var timeoutResp = new MockResponse().setResponseCode(404); - webServer.enqueue(timeoutResp); - - assertEquals(Collections.emptyList(), githubStore.getLatestDestinations()); - } - - @Test - void testGetLatestSources() throws InterruptedException { - final var timeoutResp = new MockResponse().setResponseCode(404); - webServer.enqueue(timeoutResp); - - assertEquals(Collections.emptyList(), githubStore.getLatestSources()); - } - - } - - @Nested - @DisplayName("getFile") - class GetFile { - - @Test - void testReturn() throws IOException, InterruptedException { - final var goodBody = "great day!"; - final var goodResp = new MockResponse().setResponseCode(200) - .addHeader(CONTENT_TYPE, PLAIN_TEXT) - .addHeader(CACHE_CONTROL, NO_CACHE) - .setBody(goodBody); - webServer.enqueue(goodResp); - - final var fileStr = githubStore.getFile("test-file"); - assertEquals(goodBody, fileStr); - } - - @Test - void testHttpTimeout() { - final var timeoutResp = new MockResponse().setResponseCode(200) - .addHeader(CONTENT_TYPE, PLAIN_TEXT) - .addHeader(CACHE_CONTROL, NO_CACHE) - .setBody("") - .setHeadersDelay(TIMEOUT.toSeconds() * 2, TimeUnit.SECONDS) - .setBodyDelay(TIMEOUT.toSeconds() * 2, TimeUnit.SECONDS); - webServer.enqueue(timeoutResp); - - assertThrows(HttpTimeoutException.class, () -> githubStore.getFile("test-file")); - } - - } - -} diff --git a/airbyte-commons-server/src/test/resources/icons/test-destination.svg b/airbyte-commons-server/src/test/resources/icons/test-destination.svg deleted file mode 100644 index 29fb9f8e862e5..0000000000000 --- a/airbyte-commons-server/src/test/resources/icons/test-destination.svg +++ /dev/null @@ -1,3 +0,0 @@ - - destination - diff --git a/airbyte-commons-server/src/test/resources/icons/test-source.svg b/airbyte-commons-server/src/test/resources/icons/test-source.svg deleted file mode 100644 index 7d81478ebd00a..0000000000000 --- a/airbyte-commons-server/src/test/resources/icons/test-source.svg +++ /dev/null @@ -1,3 +0,0 @@ - - source - diff --git a/airbyte-commons-server/src/test/resources/json/TestImplementation.json b/airbyte-commons-server/src/test/resources/json/TestImplementation.json deleted file mode 100644 index 3c88772c28c43..0000000000000 --- a/airbyte-commons-server/src/test/resources/json/TestImplementation.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "apiKey": "123-abc", - "hostname": "airbyte.io" -} diff --git a/airbyte-commons-server/src/test/resources/json/TestSpecification.json b/airbyte-commons-server/src/test/resources/json/TestSpecification.json deleted file mode 100644 index 399ab4e98420f..0000000000000 --- a/airbyte-commons-server/src/test/resources/json/TestSpecification.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "specification": { - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://github.com/airbytehq/airbyte/blob/master/airbyte-server/src/test/resources/json/TestSpecification.json", - "title": "TestSpecification", - "description": "information output by the connection.", - "type": "object", - "required": ["apiKey", "hostname"], - "additionalProperties": false, - "properties": { - "apiKey": { - "type": "string" - }, - "hostname": { - "type": "string" - } - } - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/03a4c904-c91d-447f-ab59-27a43b52c2fd.gz b/airbyte-commons-server/src/test/resources/migration/03a4c904-c91d-447f-ab59-27a43b52c2fd.gz deleted file mode 100644 index 0e9f6b2c40691dcc00e8abc8b4447c2ef71d8ceb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5774 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 M|K}VAcL1&c0L_PN*#H0l diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/4e00862d-5484-4f50-9860-f3bbb4317397.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/4e00862d-5484-4f50-9860-f3bbb4317397.json deleted file mode 100644 index b88d0a44331d4..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/4e00862d-5484-4f50-9860-f3bbb4317397.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "Postgres Docker", - "destinationDefinitionId": "25c5221d-dce2-4163-ade9-739ef790f503", - "workspaceId": "5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6", - "destinationId": "4e00862d-5484-4f50-9860-f3bbb4317397", - "configuration": { - "basic_normalization": true, - "username": "postgres", - "password": "password", - "database": "postgres", - "schema": "public", - "port": 3000, - "host": "localhost" - }, - "tombstone": false -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/5434615d-a3b7-4351-bc6b-a9a695555a30.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/5434615d-a3b7-4351-bc6b-a9a695555a30.json deleted file mode 100644 index 1820bef139d33..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/DESTINATION_CONNECTION/5434615d-a3b7-4351-bc6b-a9a695555a30.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "CSV", - "destinationDefinitionId": "8be1cf83-fde1-477f-a4ad-318d23c9f3c6", - "workspaceId": "5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6", - "destinationId": "5434615d-a3b7-4351-bc6b-a9a695555a30", - "configuration": { "destination_path": "csv_data" }, - "tombstone": false -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/28ffee2b-372a-4f72-9b95-8ed56a8b99c5.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/28ffee2b-372a-4f72-9b95-8ed56a8b99c5.json deleted file mode 100644 index fc15d49eb16e0..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/28ffee2b-372a-4f72-9b95-8ed56a8b99c5.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "MySQL localhost", - "sourceDefinitionId": "435bb9a5-7887-4809-aa58-28c27df0d7ad", - "workspaceId": "5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6", - "sourceId": "28ffee2b-372a-4f72-9b95-8ed56a8b99c5", - "configuration": { - "username": "root", - "password": "password", - "database": "localhost_test", - "port": 3306, - "host": "host.docker.internal" - }, - "tombstone": false -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/e48cae1a-1f5c-42cc-9ec1-a44ff7fb4969.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/e48cae1a-1f5c-42cc-9ec1-a44ff7fb4969.json deleted file mode 100644 index ee2dc444ef371..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/SOURCE_CONNECTION/e48cae1a-1f5c-42cc-9ec1-a44ff7fb4969.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "Using a source definition deleted", - "sourceDefinitionId": "4eb22946-2a79-4d20-a3e6-effd234613c3", - "workspaceId": "5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6", - "sourceId": "e48cae1a-1f5c-42cc-9ec1-a44ff7fb4969", - "configuration": { - "username": "root", - "password": "password", - "database": "localhost_test", - "port": 3306, - "host": "host.docker.internal" - }, - "tombstone": false -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/22f6c74f-5699-40ff-833c-4a879ea40133.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/22f6c74f-5699-40ff-833c-4a879ea40133.json deleted file mode 100644 index 0f41fabe8f3a9..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/22f6c74f-5699-40ff-833c-4a879ea40133.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "22f6c74f-5699-40ff-833c-4a879ea40133", - "name": "BigQuery", - "dockerRepository": "airbyte/destination-bigquery", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/bigquery", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/bigquery", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/25c5221d-dce2-4163-ade9-739ef790f503.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/25c5221d-dce2-4163-ade9-739ef790f503.json deleted file mode 100644 index 3f346d797154e..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/25c5221d-dce2-4163-ade9-739ef790f503.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "25c5221d-dce2-4163-ade9-739ef790f503", - "name": "Postgres", - "dockerRepository": "airbyte/destination-postgres", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/postgres", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/postgres", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/424892c4-daac-4491-b35d-c6688ba547ba.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/424892c4-daac-4491-b35d-c6688ba547ba.json deleted file mode 100644 index f4b70b05aaa3b..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/424892c4-daac-4491-b35d-c6688ba547ba.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "424892c4-daac-4491-b35d-c6688ba547ba", - "name": "Snowflake", - "dockerRepository": "airbyte/destination-snowflake", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/snowflake", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/snowflake", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/8be1cf83-fde1-477f-a4ad-318d23c9f3c6.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/8be1cf83-fde1-477f-a4ad-318d23c9f3c6.json deleted file mode 100644 index 9df1daa7600d0..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/8be1cf83-fde1-477f-a4ad-318d23c9f3c6.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "8be1cf83-fde1-477f-a4ad-318d23c9f3c6", - "name": "Local CSV", - "dockerRepository": "airbyte/destination-csv", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/local-csv", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/local-csv", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/a625d593-bba5-4a1c-a53d-2d246268a816.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/a625d593-bba5-4a1c-a53d-2d246268a816.json deleted file mode 100644 index 10188ba372164..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/a625d593-bba5-4a1c-a53d-2d246268a816.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "a625d593-bba5-4a1c-a53d-2d246268a816", - "name": "Local JSON", - "dockerRepository": "airbyte/destination-local-json", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/local-json", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/local-json", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/af7c921e-5892-4ff2-b6c1-4a5ab258fb7e.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/af7c921e-5892-4ff2-b6c1-4a5ab258fb7e.json deleted file mode 100644 index db3cc13e318f8..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/af7c921e-5892-4ff2-b6c1-4a5ab258fb7e.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "af7c921e-5892-4ff2-b6c1-4a5ab258fb7e", - "name": "MeiliSearch", - "dockerRepository": "airbyte/destination-meilisearch", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/meilisearch", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/meilisearch", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/f7a7d195-377f-cf5b-70a5-be6b819019dc.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/f7a7d195-377f-cf5b-70a5-be6b819019dc.json deleted file mode 100644 index 32304def896de..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_DESTINATION_DEFINITION/f7a7d195-377f-cf5b-70a5-be6b819019dc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "destinationDefinitionId": "f7a7d195-377f-cf5b-70a5-be6b819019dc", - "name": "Redshift", - "dockerRepository": "airbyte/destination-redshift", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/redshift", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/redshift", - "connectionSpecification": {}, - "supportsIncremental": true - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c.json deleted file mode 100644 index 44982b32ccabb..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "00405b19-9768-4e0c-b1ae-9fc2ee2b2a8c", - "name": "Looker", - "dockerRepository": "airbyte/source-looker", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-looker", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/looker", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2470e835-feaf-4db6-96f3-70fd645acc77.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2470e835-feaf-4db6-96f3-70fd645acc77.json deleted file mode 100644 index 4d81443752283..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2470e835-feaf-4db6-96f3-70fd645acc77.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "2470e835-feaf-4db6-96f3-70fd645acc77", - "name": "Salesforce", - "dockerRepository": "airbyte/source-salesforce-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-salesforce-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/salesforce", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2af123bf-0aaf-4e0d-9784-cb497f23741a.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2af123bf-0aaf-4e0d-9784-cb497f23741a.json deleted file mode 100644 index 1b2292279099a..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/2af123bf-0aaf-4e0d-9784-cb497f23741a.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "2af123bf-0aaf-4e0d-9784-cb497f23741a", - "name": "Appstore", - "dockerRepository": "airbyte/source-appstore-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-appstore-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/appstore", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/396e4ca3-8a97-4b85-aa4e-c9d8c2d5f992.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/396e4ca3-8a97-4b85-aa4e-c9d8c2d5f992.json deleted file mode 100644 index 48b6d163439e9..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/396e4ca3-8a97-4b85-aa4e-c9d8c2d5f992.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "396e4ca3-8a97-4b85-aa4e-c9d8c2d5f992", - "name": "Braintree", - "dockerRepository": "airbyte/source-braintree-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-braintree-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/braintree", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/41375467-61ae-4204-8e38-e2b8b7365f23.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/41375467-61ae-4204-8e38-e2b8b7365f23.json deleted file mode 100644 index b706fc7d9f1a5..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/41375467-61ae-4204-8e38-e2b8b7365f23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "41375467-61ae-4204-8e38-e2b8b7365f23", - "name": "Slack", - "dockerRepository": "airbyte/source-slack-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/repository/docker/airbyte/source-slack-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/slack", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/435bb9a5-7887-4809-aa58-28c27df0d7ad.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/435bb9a5-7887-4809-aa58-28c27df0d7ad.json deleted file mode 100644 index 1b9e159ba87c7..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/435bb9a5-7887-4809-aa58-28c27df0d7ad.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "435bb9a5-7887-4809-aa58-28c27df0d7ad", - "name": "MySQL", - "dockerRepository": "airbyte/source-mysql", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/sources/mysql", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/mysql", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/445831eb-78db-4b1f-8f1f-0d96ad8739e2.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/445831eb-78db-4b1f-8f1f-0d96ad8739e2.json deleted file mode 100644 index a73646d3aa07d..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/445831eb-78db-4b1f-8f1f-0d96ad8739e2.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "445831eb-78db-4b1f-8f1f-0d96ad8739e2", - "name": "Drift", - "dockerRepository": "airbyte/source-drift", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-drift", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/drift", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/4eb22946-2a79-4d20-a3e6-effd234613c3.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/4eb22946-2a79-4d20-a3e6-effd234613c3.json deleted file mode 100644 index eb7306ee608fe..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/4eb22946-2a79-4d20-a3e6-effd234613c3.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "4eb22946-2a79-4d20-a3e6-effd234613c3", - "name": "Old connector still being used", - "dockerRepository": "airbyte/source-mysql", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://docs.airbyte.io/integrations/sources/mysql", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/destinations/mysql", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/57eb1576-8f52-463d-beb6-2e107cdf571d.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/57eb1576-8f52-463d-beb6-2e107cdf571d.json deleted file mode 100644 index e681e0eaac140..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/57eb1576-8f52-463d-beb6-2e107cdf571d.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "57eb1576-8f52-463d-beb6-2e107cdf571d", - "name": "Hubspot", - "dockerRepository": "airbyte/source-hubspot-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://https://docs.airbyte.io/integrations/sources/hubspot", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/hubspot", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/59f1e50a-331f-4f09-b3e8-2e8d4d355f44.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/59f1e50a-331f-4f09-b3e8-2e8d4d355f44.json deleted file mode 100644 index fca454d4c1819..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/59f1e50a-331f-4f09-b3e8-2e8d4d355f44.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "59f1e50a-331f-4f09-b3e8-2e8d4d355f44", - "name": "Greenhouse", - "dockerRepository": "airbyte/source-greenhouse", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://https://docs.airbyte.io/integrations/sources/greenhouse", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/greenhouse", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/68e63de2-bb83-4c7e-93fa-a8a9051e3993.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/68e63de2-bb83-4c7e-93fa-a8a9051e3993.json deleted file mode 100644 index 93812f6b85b23..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/68e63de2-bb83-4c7e-93fa-a8a9051e3993.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "68e63de2-bb83-4c7e-93fa-a8a9051e3993", - "name": "Jira", - "dockerRepository": "airbyte/source-jira", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-jira", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/jira", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/71607ba1-c0ac-4799-8049-7f4b90dd50f7.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/71607ba1-c0ac-4799-8049-7f4b90dd50f7.json deleted file mode 100644 index 11ce44b6c97e4..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/71607ba1-c0ac-4799-8049-7f4b90dd50f7.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "71607ba1-c0ac-4799-8049-7f4b90dd50f7", - "name": "Google Sheets", - "dockerRepository": "airbyte/source-google-sheets", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/repository/docker/airbyte/source-google-sheets", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/google-sheets", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/778daa7c-feaf-4db6-96f3-70fd645acc77.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/778daa7c-feaf-4db6-96f3-70fd645acc77.json deleted file mode 100644 index d98d85610c7e7..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/778daa7c-feaf-4db6-96f3-70fd645acc77.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "778daa7c-feaf-4db6-96f3-70fd645acc77", - "name": "File", - "dockerRepository": "airbyte/source-file", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-file", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/file", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/859e501d-2b67-471f-91bb-1c801414d28f.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/859e501d-2b67-471f-91bb-1c801414d28f.json deleted file mode 100644 index 80888b0d66a32..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/859e501d-2b67-471f-91bb-1c801414d28f.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "859e501d-2b67-471f-91bb-1c801414d28f", - "name": "Mixpanel", - "dockerRepository": "airbyte/source-mixpanel-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-mixpanel-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/mixpanel", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9e0556f4-69df-4522-a3fb-03264d36b348.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9e0556f4-69df-4522-a3fb-03264d36b348.json deleted file mode 100644 index 75dec47c07dc0..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9e0556f4-69df-4522-a3fb-03264d36b348.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "9e0556f4-69df-4522-a3fb-03264d36b348", - "name": "Marketo", - "dockerRepository": "airbyte/source-marketo-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-marketo-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/marketo", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9fed261d-d107-47fd-8c8b-323023db6e20.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9fed261d-d107-47fd-8c8b-323023db6e20.json deleted file mode 100644 index 5f76fd4926951..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/9fed261d-d107-47fd-8c8b-323023db6e20.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "9fed261d-d107-47fd-8c8b-323023db6e20", - "name": "Exchange Rates Api", - "dockerRepository": "airbyte/source-exchangeratesapi-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/integration-singer-exchangeratesapi_io-source", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/exchangeratesapi", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/aea2fd0d-377d-465e-86c0-4fdc4f688e51.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/aea2fd0d-377d-465e-86c0-4fdc4f688e51.json deleted file mode 100644 index ab91537728421..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/aea2fd0d-377d-465e-86c0-4fdc4f688e51.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "aea2fd0d-377d-465e-86c0-4fdc4f688e51", - "name": "Zoom", - "dockerRepository": "airbyte/source-zoom-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-zoom-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/zoom", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b03a9f3e-22a5-11eb-adc1-0242ac120002.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b03a9f3e-22a5-11eb-adc1-0242ac120002.json deleted file mode 100644 index b08cfcc582590..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b03a9f3e-22a5-11eb-adc1-0242ac120002.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "b03a9f3e-22a5-11eb-adc1-0242ac120002", - "name": "Mailchimp", - "dockerRepository": "airbyte/source-mailchimp", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-mailchimp", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/mailchimp", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b1892b11-788d-44bd-b9ec-3a436f7b54ce.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b1892b11-788d-44bd-b9ec-3a436f7b54ce.json deleted file mode 100644 index 82140f27bdef2..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b1892b11-788d-44bd-b9ec-3a436f7b54ce.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "b1892b11-788d-44bd-b9ec-3a436f7b54ce", - "name": "Shopify", - "dockerRepository": "airbyte/source-shopify-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-shopify-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/shopify", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b5ea17b1-f170-46dc-bc31-cc744ca984c1.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b5ea17b1-f170-46dc-bc31-cc744ca984c1.json deleted file mode 100644 index 91c409ba1ed95..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/b5ea17b1-f170-46dc-bc31-cc744ca984c1.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "b5ea17b1-f170-46dc-bc31-cc744ca984c1", - "name": "Microsoft SQL Server (MSSQL)", - "dockerRepository": "airbyte/source-mssql", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-mssql", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/mssql", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/cd42861b-01fc-4658-a8ab-5d11d0510f01.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/cd42861b-01fc-4658-a8ab-5d11d0510f01.json deleted file mode 100644 index 4b6ac4817bf1d..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/cd42861b-01fc-4658-a8ab-5d11d0510f01.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "cd42861b-01fc-4658-a8ab-5d11d0510f01", - "name": "Recurly", - "dockerRepository": "airbyte/source-recurly", - "dockerImageTag": "0.3.1", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-recurly", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/recurly", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d2147be5-fa36-4936-977e-f031affa5895.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d2147be5-fa36-4936-977e-f031affa5895.json deleted file mode 100644 index cce976b11c978..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d2147be5-fa36-4936-977e-f031affa5895.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "d2147be5-fa36-4936-977e-f031affa5895", - "name": "Old Connector", - "dockerRepository": "airbyte/source-appstore-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-appstore-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/appstore", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d29764f8-80d7-4dd7-acbe-1a42005ee5aa.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d29764f8-80d7-4dd7-acbe-1a42005ee5aa.json deleted file mode 100644 index 426c111fece46..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d29764f8-80d7-4dd7-acbe-1a42005ee5aa.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "d29764f8-80d7-4dd7-acbe-1a42005ee5aa", - "name": "Zendesk Support", - "dockerRepository": "airbyte/source-zendesk-support-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-zendesk-support-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/zendesk-support", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d8313939-3782-41b0-be29-b3ca20d8dd3a.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d8313939-3782-41b0-be29-b3ca20d8dd3a.json deleted file mode 100644 index 5121a300a7704..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/d8313939-3782-41b0-be29-b3ca20d8dd3a.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "d8313939-3782-41b0-be29-b3ca20d8dd3a", - "name": "Intercom", - "dockerRepository": "airbyte/source-intercom-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-intercom-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/intercom", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/decd338e-5647-4c0b-adf4-da0e75f5a750.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/decd338e-5647-4c0b-adf4-da0e75f5a750.json deleted file mode 100644 index 79bf62ad40a6f..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/decd338e-5647-4c0b-adf4-da0e75f5a750.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "decd338e-5647-4c0b-adf4-da0e75f5a750", - "name": "Postgres", - "dockerRepository": "airbyte/source-postgres", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-postgres", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/postgres", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e094cb9a-26de-4645-8761-65c0c425d1de.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e094cb9a-26de-4645-8761-65c0c425d1de.json deleted file mode 100644 index 4e59550a35777..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e094cb9a-26de-4645-8761-65c0c425d1de.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "e094cb9a-26de-4645-8761-65c0c425d1de", - "name": "Stripe", - "dockerRepository": "airbyte/source-stripe-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/integration-singer-stripe-source", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/stripe", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e7778cfc-e97c-4458-9ecb-b4f2bba8946c.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e7778cfc-e97c-4458-9ecb-b4f2bba8946c.json deleted file mode 100644 index f265921c0876a..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e7778cfc-e97c-4458-9ecb-b4f2bba8946c.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "e7778cfc-e97c-4458-9ecb-b4f2bba8946c", - "name": "Facebook Marketing", - "dockerRepository": "airbyte/source-facebook-marketing", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-facebook-marketing", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/facebook", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e87ffa8e-a3b5-f69c-9076-6011339de1f6.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e87ffa8e-a3b5-f69c-9076-6011339de1f6.json deleted file mode 100644 index ad2e7c6534749..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/e87ffa8e-a3b5-f69c-9076-6011339de1f6.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "e87ffa8e-a3b5-f69c-9076-6011339de1f6", - "name": "Redshift", - "dockerRepository": "airbyte/source-redshift", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/repository/docker/airbyte/source-redshift", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/redshift", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/eaf50f04-21dd-4620-913b-2a83f5635227.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/eaf50f04-21dd-4620-913b-2a83f5635227.json deleted file mode 100644 index 9df0eb9bd85c8..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/eaf50f04-21dd-4620-913b-2a83f5635227.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "eaf50f04-21dd-4620-913b-2a83f5635227", - "name": "Microsoft teams", - "dockerRepository": "airbyte/source-microsoft-teams", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-microsoft-teams", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/microsoft-teams", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ec4b9503-13cb-48ab-a4ab-6ade4be46567.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ec4b9503-13cb-48ab-a4ab-6ade4be46567.json deleted file mode 100644 index 5beabc83f6a67..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ec4b9503-13cb-48ab-a4ab-6ade4be46567.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "ec4b9503-13cb-48ab-a4ab-6ade4be46567", - "name": "Freshdesk", - "dockerRepository": "airbyte/source-freshdesk", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-freshdesk", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/freshdesk", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ed799e2b-2158-4c66-8da4-b40fe63bc72a.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ed799e2b-2158-4c66-8da4-b40fe63bc72a.json deleted file mode 100644 index ebe806009ad69..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ed799e2b-2158-4c66-8da4-b40fe63bc72a.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "ed799e2b-2158-4c66-8da4-b40fe63bc72a", - "name": "Plaid", - "dockerRepository": "airbyte/source-plaid", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-plaid", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/plaid", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ef69ef6e-aa7f-4af1-a01d-ef775033524e.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ef69ef6e-aa7f-4af1-a01d-ef775033524e.json deleted file mode 100644 index 2bf8badeebe28..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/ef69ef6e-aa7f-4af1-a01d-ef775033524e.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "ef69ef6e-aa7f-4af1-a01d-ef775033524e", - "name": "GitHub", - "dockerRepository": "airbyte/source-github-singer", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-github-singer", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/github", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87.json deleted file mode 100644 index 84bf72d3da15d..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SOURCE_DEFINITION/fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "sourceDefinitionId": "fbb5fbe2-16ad-4cf4-af7d-ff9d9c316c87", - "name": "Sendgrid", - "dockerRepository": "airbyte/source-sendgrid", - "dockerImageTag": "0.2.0", - "documentationUrl": "https://hub.docker.com/r/airbyte/source-sendgrid", - "spec": { - "documentationUrl": "https://docs.airbyte.io/integrations/sources/sendgrid", - "connectionSpecification": {} - } -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json deleted file mode 100644 index 281271e9b9404..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "prefix": "", - "sourceId": "28ffee2b-372a-4f72-9b95-8ed56a8b99c5", - "destinationId": "5434615d-a3b7-4351-bc6b-a9a695555a30", - "connectionId": "49dae3f0-158b-4737-b6e4-0eed77d4b74e", - "name": "default", - "catalog": { - "streams": [ - { - "stream": { - "name": "localhost_test.new_table", - "json_schema": { - "type": "object", - "properties": { - "id": { "type": "number" }, - "val": { "type": "string" } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [] - }, - "sync_mode": "full_refresh", - "cursor_field": [] - }, - { - "stream": { - "name": "localhost_test.test_table", - "json_schema": { - "type": "object", - "properties": { - "id": { "type": "number" }, - "val": { "type": "string" }, - "updated_at": { "type": "string" } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [] - }, - "sync_mode": "incremental", - "cursor_field": ["updated_at"] - } - ] - }, - "status": "active" -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/a294256f-1abe-4837-925f-91602c7207b4.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/a294256f-1abe-4837-925f-91602c7207b4.json deleted file mode 100644 index 9a8b5318a58f5..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC/a294256f-1abe-4837-925f-91602c7207b4.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "prefix": "", - "sourceId": "28ffee2b-372a-4f72-9b95-8ed56a8b99c5", - "destinationId": "4e00862d-5484-4f50-9860-f3bbb4317397", - "connectionId": "a294256f-1abe-4837-925f-91602c7207b4", - "name": "default", - "catalog": { - "streams": [ - { - "stream": { - "name": "localhost_test.new_table", - "json_schema": { - "type": "object", - "properties": { - "id": { "type": "number" }, - "val": { "type": "string" } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [] - }, - "sync_mode": "full_refresh", - "cursor_field": [] - }, - { - "stream": { - "name": "localhost_test.test_table", - "json_schema": { - "type": "object", - "properties": { - "id": { "type": "number" }, - "val": { "type": "string" }, - "updated_at": { "type": "string" } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [] - }, - "sync_mode": "incremental", - "cursor_field": ["updated_at"] - } - ] - }, - "status": "active" -} diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json deleted file mode 100644 index 3c9c3fb1825b4..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/49dae3f0-158b-4737-b6e4-0eed77d4b74e.json +++ /dev/null @@ -1 +0,0 @@ -{ "connectionId": "49dae3f0-158b-4737-b6e4-0eed77d4b74e", "manual": true } diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/a294256f-1abe-4837-925f-91602c7207b4.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/a294256f-1abe-4837-925f-91602c7207b4.json deleted file mode 100644 index 0ed8884c4750a..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_SYNC_SCHEDULE/a294256f-1abe-4837-925f-91602c7207b4.json +++ /dev/null @@ -1 +0,0 @@ -{ "connectionId": "a294256f-1abe-4837-925f-91602c7207b4", "manual": true } diff --git a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_WORKSPACE/5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6.json b/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_WORKSPACE/5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6.json deleted file mode 100644 index 864257ed89661..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/dummy_data/config/STANDARD_WORKSPACE/5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "workspaceId": "5ae6b09b-fdec-41af-aaf7-7d94cfc33ef6", - "customerId": "17f90b72-5ae4-40b7-bc49-d6c2943aea57", - "name": "default", - "slug": "default", - "initialSetupComplete": true, - "anonymousDataCollection": false, - "news": false, - "securityUpdates": false, - "displaySetupWizard": false -} diff --git a/airbyte-commons-server/src/test/resources/migration/schema.sql b/airbyte-commons-server/src/test/resources/migration/schema.sql deleted file mode 100644 index dd2b7c507300f..0000000000000 --- a/airbyte-commons-server/src/test/resources/migration/schema.sql +++ /dev/null @@ -1,82 +0,0 @@ --- extensions -CREATE - EXTENSION IF NOT EXISTS "uuid-ossp"; - --- types -CREATE - TYPE JOB_STATUS AS ENUM( - 'pending', - 'running', - 'incomplete', - 'failed', - 'succeeded', - 'cancelled' - ); - -CREATE - TYPE ATTEMPT_STATUS AS ENUM( - 'running', - 'failed', - 'succeeded' - ); - -CREATE - TYPE JOB_CONFIG_TYPE AS ENUM( - 'check_connection_source', - 'check_connection_destination', - 'discover_schema', - 'get_spec', - 'sync', - 'reset_connection' - ); - --- tables -CREATE - TABLE - AIRBYTE_METADATA( - KEY VARCHAR(255) PRIMARY KEY, - value VARCHAR(255) - ); - -CREATE - TABLE - JOBS( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - config_type JOB_CONFIG_TYPE, - SCOPE VARCHAR(255), - config JSONB, - status JOB_STATUS, - started_at TIMESTAMPTZ, - created_at TIMESTAMPTZ, - updated_at TIMESTAMPTZ - ); - -CREATE - TABLE - ATTEMPTS( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - job_id BIGINT, - attempt_number INTEGER, - log_path VARCHAR(255), - OUTPUT JSONB, - status ATTEMPT_STATUS, - created_at TIMESTAMPTZ, - updated_at TIMESTAMPTZ, - ended_at TIMESTAMPTZ - ); - -CREATE - UNIQUE INDEX job_attempt_idx ON - ATTEMPTS( - job_id, - attempt_number - ); - --- entries -INSERT - INTO - AIRBYTE_METADATA - VALUES( - 'server_uuid', - uuid_generate_v4() - ); diff --git a/airbyte-connector-builder-server/.coveragerc b/airbyte-connector-builder-server/.coveragerc deleted file mode 100644 index 034c0c0c28f5e..0000000000000 --- a/airbyte-connector-builder-server/.coveragerc +++ /dev/null @@ -1,3 +0,0 @@ -[report] -# show lines missing coverage -show_missing = true diff --git a/airbyte-connector-builder-server/.dockerignore b/airbyte-connector-builder-server/.dockerignore deleted file mode 100644 index 5cea6d6cbdd19..0000000000000 --- a/airbyte-connector-builder-server/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -build -!build/airbyte_api_client -.venv -connector_builder.egg-info diff --git a/airbyte-connector-builder-server/.gitignore b/airbyte-connector-builder-server/.gitignore deleted file mode 100644 index 2456084a5e540..0000000000000 --- a/airbyte-connector-builder-server/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.coverage -.venv -state_*.yaml diff --git a/airbyte-connector-builder-server/.python-version b/airbyte-connector-builder-server/.python-version deleted file mode 100644 index a9f8d1be337f7..0000000000000 --- a/airbyte-connector-builder-server/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9.11 diff --git a/airbyte-connector-builder-server/CDK_VERSION b/airbyte-connector-builder-server/CDK_VERSION deleted file mode 100644 index 94a5fe438afc3..0000000000000 --- a/airbyte-connector-builder-server/CDK_VERSION +++ /dev/null @@ -1 +0,0 @@ -0.25.0 \ No newline at end of file diff --git a/airbyte-connector-builder-server/CHANGELOG.md b/airbyte-connector-builder-server/CHANGELOG.md deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/airbyte-connector-builder-server/Dockerfile b/airbyte-connector-builder-server/Dockerfile deleted file mode 100644 index 7badf775681d7..0000000000000 --- a/airbyte-connector-builder-server/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM python:3.9-slim as base - -RUN apt-get upgrade \ - && pip install --upgrade pip - -WORKDIR /home/connector-builder-server -COPY . ./ - -RUN pip install --no-cache-dir . - -ENTRYPOINT ["uvicorn", "connector_builder.entrypoint:app", "--host", "0.0.0.0", "--port", "80"] - -LABEL io.airbyte.version=0.40.32 -LABEL io.airbyte.name=airbyte/connector-builder-server diff --git a/airbyte-connector-builder-server/README.md b/airbyte-connector-builder-server/README.md deleted file mode 100644 index eb6d5f83bcec0..0000000000000 --- a/airbyte-connector-builder-server/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Connector builder - - -## Getting started - -Set up the virtual environment and install dependencies -```bash -python -m venv .venv -source .venv/bin/activate -pip install . -``` - -Then run the server -```bash -uvicorn connector_builder.entrypoint:app --host 0.0.0.0 --port 8080 -``` - -The server is now reachable on localhost:8080 - -## Changing the used CDK version - -Update the `airbyte-connector-builder-server/CDK_VERSION` file to point to the target version. -This will make sure both this project and the webapp depending on it will stay in sync. - -### OpenAPI generation - -Run it via Gradle by running this from the Airbyte project root: -```bash -./gradlew :airbyte-connector-builder-server:generateOpenApiPythonServer -``` diff --git a/airbyte-connector-builder-server/build.gradle b/airbyte-connector-builder-server/build.gradle deleted file mode 100644 index 4f8bb1e08b0de..0000000000000 --- a/airbyte-connector-builder-server/build.gradle +++ /dev/null @@ -1,61 +0,0 @@ -import org.openapitools.generator.gradle.plugin.tasks.GenerateTask - -plugins { - id "org.openapi.generator" version "5.3.1" - id 'airbyte-python-docker' - id 'airbyte-docker' -} - -airbytePythonDocker { - moduleDirectory 'connector_builder' -} - -task generateOpenApiPythonServer(type: GenerateTask) { - outputs.upToDateWhen { false } - - def generatedCodeDir = "$buildDir/airbyte_connector_builder_server" - inputSpec = "$rootDir.absolutePath/airbyte-connector-builder-server/src/main/openapi/openapi.yaml" - outputDir = generatedCodeDir - - generatorName = "python-fastapi" - configFile = "$projectDir/openapi/generator_config.yaml" - templateDir = "$projectDir/openapi/templates" - packageName = "connector_builder.generated" - - // After we generate, we're only interested in the API declaration and the generated pydantic models. - // So we copy those from the build/ directory - doLast { - def sourceDir = "$generatedCodeDir/src/connector_builder/generated/" - def targetDir = "$projectDir/connector_builder/generated" - mkdir targetDir - copy { - from "$sourceDir/apis" - include "*_interface.py", "__init__.py" - into "$targetDir/apis" - } - copy { - from "$sourceDir/models" - include "*.py" - into "$targetDir/models" - } - } -} - -project.build.dependsOn(generateOpenApiPythonServer) - -// java modules such as airbyte-server can use copyGeneratedTar to copy the files to the docker image -// We cannot do this here because we don't generate a tar file -// Instead, we copy the files into the build directory so they can be copied to the docker container -task prepareBuild(type: Copy) { - from layout.projectDirectory.file(".") - exclude '.*' - exclude 'build' - exclude '**/*.pyc' - - into layout.buildDirectory.dir("docker") -} - -tasks.named("buildDockerImage") { - dependsOn prepareBuild - dependsOn copyDocker -} diff --git a/airbyte-connector-builder-server/connector_builder/__init__.py b/airbyte-connector-builder-server/connector_builder/__init__.py deleted file mode 100644 index c941b30457953..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# diff --git a/airbyte-connector-builder-server/connector_builder/entrypoint.py b/airbyte-connector-builder-server/connector_builder/entrypoint.py deleted file mode 100644 index 593f6b672f67a..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/entrypoint.py +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from connector_builder.generated.apis.default_api_interface import initialize_router -from connector_builder.impl.default_api import DefaultApiImpl -from connector_builder.impl.low_code_cdk_adapter import LowCodeSourceAdapterFactory -from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware - -_MAXIMUM_NUMBER_OF_PAGES_PER_SLICE = 5 -_MAXIMUM_NUMBER_OF_SLICES = 5 -_ADAPTER_FACTORY = LowCodeSourceAdapterFactory(_MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, _MAXIMUM_NUMBER_OF_SLICES) - -app = FastAPI( - title="Connector Builder Server API", - description="Connector Builder Server API ", - version="1.0.0", -) - -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - -app.include_router(initialize_router(DefaultApiImpl(_ADAPTER_FACTORY, _MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, _MAXIMUM_NUMBER_OF_SLICES))) diff --git a/airbyte-connector-builder-server/connector_builder/generated/apis/__init__.py b/airbyte-connector-builder-server/connector_builder/generated/apis/__init__.py deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/airbyte-connector-builder-server/connector_builder/generated/apis/default_api_interface.py b/airbyte-connector-builder-server/connector_builder/generated/apis/default_api_interface.py deleted file mode 100644 index d21d514bdbe9e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/apis/default_api_interface.py +++ /dev/null @@ -1,173 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -# This file was auto-generated from Airbyte's custom OpenAPI templates. Do not edit it manually. -# coding: utf-8 - -import inspect -from abc import ABC, abstractmethod -from typing import Callable, Dict, List # noqa: F401 - -from fastapi import ( # noqa: F401 - APIRouter, - Body, - Cookie, - Depends, - Form, - Header, - Path, - Query, - Response, - Security, - status, -) - -from connector_builder.generated.models.extra_models import TokenModel # noqa: F401 - - -from connector_builder.generated.models.invalid_input_exception_info import InvalidInputExceptionInfo -from connector_builder.generated.models.known_exception_info import KnownExceptionInfo -from connector_builder.generated.models.resolve_manifest import ResolveManifest -from connector_builder.generated.models.resolve_manifest_request_body import ResolveManifestRequestBody -from connector_builder.generated.models.stream_read import StreamRead -from connector_builder.generated.models.stream_read_request_body import StreamReadRequestBody -from connector_builder.generated.models.streams_list_read import StreamsListRead -from connector_builder.generated.models.streams_list_request_body import StreamsListRequestBody - - -class DefaultApi(ABC): - """ - NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - Do not edit the class manually. - """ - - @abstractmethod - async def get_manifest_template( - self, - ) -> str: - """ - Return a connector manifest template to use as the default value for the yaml editor - """ - - @abstractmethod - async def list_streams( - self, - streams_list_request_body: StreamsListRequestBody = Body(None, description=""), - ) -> StreamsListRead: - """ - List all streams present in the connector manifest, along with their specific request URLs - """ - - @abstractmethod - async def read_stream( - self, - stream_read_request_body: StreamReadRequestBody = Body(None, description=""), - ) -> StreamRead: - """ - Reads a specific stream in the source. TODO in a later phase - only read a single slice of data. - """ - - @abstractmethod - async def resolve_manifest( - self, - resolve_manifest_request_body: ResolveManifestRequestBody = Body(None, description=""), - ) -> ResolveManifest: - """ - Given a JSON manifest, returns a JSON manifest with all of the $refs and $options resolved and flattened - """ - - -def _assert_signature_is_set(method: Callable) -> None: - """ - APIRouter().add_api_route expects the input method to have a signature. It gets signatures - by running inspect.signature(method) under the hood. - - In the case that an instance method does not declare "self" as an input parameter (due to developer error - for example), then the call to inspect.signature() raises a ValueError and fails. - - Ideally, we'd automatically detect & correct this problem. To do that, we'd need to do - setattr(method, "__signature__", ) but that's not possible because instance - methods (i.e the input to this function) are object subclasses, and you can't use setattr on objects - (https://stackoverflow.com/a/12839070/3237889) - - The workaround this method implements is to raise an exception at runtime if the input method fails - when inspect.signature() is called. This is good enough because the error will be detected - immediately when the developer tries to run the server, so builds should very quickly fail and this - will practically never make it to a production scenario. - """ - try: - inspect.signature(method) - except ValueError as e: - # Based on empirical observation, the call to inspect fails with a ValueError - # with exactly one argument: "invalid method signature" - if e.args and len(e.args) == 1 and e.args[0] == "invalid method signature": - # I couldn't figure out how to setattr on a "method" object to populate the signature. For now just kick - # it back to the developer and tell them to set the "self" variable - raise Exception(f"Method {method.__name__} in class {type(method.__self__).__name__} must declare the variable 'self'. ") - else: - raise - - -def initialize_router(api: DefaultApi) -> APIRouter: - router = APIRouter() - - _assert_signature_is_set(api.get_manifest_template) - router.add_api_route( - "/v1/manifest_template", - endpoint=api.get_manifest_template, - methods=["GET"], - responses={ - 200: {"model": str, "description": "Successful operation"}, - }, - tags=["default"], - summary="Return a connector manifest template to use as the default value for the yaml editor", - response_model_by_alias=True, - ) - - _assert_signature_is_set(api.list_streams) - router.add_api_route( - "/v1/streams/list", - endpoint=api.list_streams, - methods=["POST"], - responses={ - 200: {"model": StreamsListRead, "description": "Successful operation"}, - 400: {"model": KnownExceptionInfo, "description": "Exception occurred; see message for details."}, - 422: {"model": InvalidInputExceptionInfo, "description": "Input failed validation"}, - }, - tags=["default"], - summary="List all streams present in the connector manifest, along with their specific request URLs", - response_model_by_alias=True, - ) - - _assert_signature_is_set(api.read_stream) - router.add_api_route( - "/v1/stream/read", - endpoint=api.read_stream, - methods=["POST"], - responses={ - 200: {"model": StreamRead, "description": "Successful operation"}, - 400: {"model": KnownExceptionInfo, "description": "Exception occurred; see message for details."}, - 422: {"model": InvalidInputExceptionInfo, "description": "Input failed validation"}, - }, - tags=["default"], - summary="Reads a specific stream in the source. TODO in a later phase - only read a single slice of data.", - response_model_by_alias=True, - ) - - _assert_signature_is_set(api.resolve_manifest) - router.add_api_route( - "/v1/manifest/resolve", - endpoint=api.resolve_manifest, - methods=["POST"], - responses={ - 200: {"model": ResolveManifest, "description": "Successful operation"}, - 400: {"model": KnownExceptionInfo, "description": "Exception occurred; see message for details."}, - 422: {"model": InvalidInputExceptionInfo, "description": "Input failed validation"}, - }, - tags=["default"], - summary="Given a JSON manifest, returns a JSON manifest with all of the $refs and $options resolved and flattened", - response_model_by_alias=True, - ) - - - return router diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/__init__.py b/airbyte-connector-builder-server/connector_builder/generated/models/__init__.py deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/add_fields.py b/airbyte-connector-builder-server/connector_builder/generated/models/add_fields.py deleted file mode 100644 index ae3c26318e442..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/add_fields.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.add_fields_all_of import AddFieldsAllOf -from connector_builder.generated.models.added_field_definition import AddedFieldDefinition -from connector_builder.generated.models.parsed_add_field_definition import ParsedAddFieldDefinition - - -class AddFields(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - AddFields - a model defined in OpenAPI - - fields: The fields of this AddFields. - parsed_fields: The parsed_fields of this AddFields [Optional]. - """ - - fields: List[AddedFieldDefinition] = Field(alias="fields") - parsed_fields: Optional[List[ParsedAddFieldDefinition]] = Field(alias="_parsed_fields", default=None) - -AddFields.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/add_fields_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/add_fields_all_of.py deleted file mode 100644 index fec6699e211d9..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/add_fields_all_of.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.added_field_definition import AddedFieldDefinition -from connector_builder.generated.models.parsed_add_field_definition import ParsedAddFieldDefinition - - -class AddFieldsAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - AddFieldsAllOf - a model defined in OpenAPI - - fields: The fields of this AddFieldsAllOf. - parsed_fields: The parsed_fields of this AddFieldsAllOf [Optional]. - """ - - fields: List[AddedFieldDefinition] = Field(alias="fields") - parsed_fields: Optional[List[ParsedAddFieldDefinition]] = Field(alias="_parsed_fields", default=None) - -AddFieldsAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/added_field_definition.py b/airbyte-connector-builder-server/connector_builder/generated/models/added_field_definition.py deleted file mode 100644 index 622683e02bcf0..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/added_field_definition.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class AddedFieldDefinition(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - AddedFieldDefinition - a model defined in OpenAPI - - path: The path of this AddedFieldDefinition. - value: The value of this AddedFieldDefinition. - """ - - path: List[str] = Field(alias="path") - value: AnyOfInterpolatedStringstring = Field(alias="value") - -AddedFieldDefinition.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator.py b/airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator.py deleted file mode 100644 index c9b4ed8abd5fc..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.api_key_authenticator_all_of import ApiKeyAuthenticatorAllOf - - -class ApiKeyAuthenticator(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ApiKeyAuthenticator - a model defined in OpenAPI - - header: The header of this ApiKeyAuthenticator. - api_token: The api_token of this ApiKeyAuthenticator. - config: The config of this ApiKeyAuthenticator. - """ - - header: AnyOfInterpolatedStringstring = Field(alias="header") - api_token: AnyOfInterpolatedStringstring = Field(alias="api_token") - config: Dict[str, Any] = Field(alias="config") - -ApiKeyAuthenticator.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator_all_of.py deleted file mode 100644 index bf7546979880d..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/api_key_authenticator_all_of.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class ApiKeyAuthenticatorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ApiKeyAuthenticatorAllOf - a model defined in OpenAPI - - header: The header of this ApiKeyAuthenticatorAllOf. - api_token: The api_token of this ApiKeyAuthenticatorAllOf. - config: The config of this ApiKeyAuthenticatorAllOf. - """ - - header: AnyOfInterpolatedStringstring = Field(alias="header") - api_token: AnyOfInterpolatedStringstring = Field(alias="api_token") - config: Dict[str, Any] = Field(alias="config") - -ApiKeyAuthenticatorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator.py b/airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator.py deleted file mode 100644 index 05ec03210336c..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.basic_http_authenticator_all_of import BasicHttpAuthenticatorAllOf - - -class BasicHttpAuthenticator(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - BasicHttpAuthenticator - a model defined in OpenAPI - - username: The username of this BasicHttpAuthenticator. - config: The config of this BasicHttpAuthenticator. - password: The password of this BasicHttpAuthenticator [Optional]. - """ - - username: AnyOfInterpolatedStringstring = Field(alias="username") - config: Dict[str, Any] = Field(alias="config") - password: Optional[AnyOfInterpolatedStringstring] = Field(alias="password", default=None) - -BasicHttpAuthenticator.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator_all_of.py deleted file mode 100644 index 46aec5658cc3d..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/basic_http_authenticator_all_of.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class BasicHttpAuthenticatorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - BasicHttpAuthenticatorAllOf - a model defined in OpenAPI - - username: The username of this BasicHttpAuthenticatorAllOf. - config: The config of this BasicHttpAuthenticatorAllOf. - password: The password of this BasicHttpAuthenticatorAllOf [Optional]. - """ - - username: AnyOfInterpolatedStringstring = Field(alias="username") - config: Dict[str, Any] = Field(alias="config") - password: Optional[AnyOfInterpolatedStringstring] = Field(alias="password", default=None) - -BasicHttpAuthenticatorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator.py b/airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator.py deleted file mode 100644 index a599282e3a7f0..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.bearer_authenticator_all_of import BearerAuthenticatorAllOf - - -class BearerAuthenticator(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - BearerAuthenticator - a model defined in OpenAPI - - api_token: The api_token of this BearerAuthenticator. - config: The config of this BearerAuthenticator. - """ - - api_token: AnyOfInterpolatedStringstring = Field(alias="api_token") - config: Dict[str, Any] = Field(alias="config") - -BearerAuthenticator.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator_all_of.py deleted file mode 100644 index 8ed9ce407402d..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/bearer_authenticator_all_of.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class BearerAuthenticatorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - BearerAuthenticatorAllOf - a model defined in OpenAPI - - api_token: The api_token of this BearerAuthenticatorAllOf. - config: The config of this BearerAuthenticatorAllOf. - """ - - api_token: AnyOfInterpolatedStringstring = Field(alias="api_token") - config: Dict[str, Any] = Field(alias="config") - -BearerAuthenticatorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer.py b/airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer.py deleted file mode 100644 index b388be6bfb317..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_cartesian_product_stream_slicer_datetime_stream_slicer_list_stream_slicer_single_slice_substream_slicer import AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer -from connector_builder.generated.models.cartesian_product_stream_slicer_all_of import CartesianProductStreamSlicerAllOf -from connector_builder.generated.models.stream_slicer import StreamSlicer - - -class CartesianProductStreamSlicer(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CartesianProductStreamSlicer - a model defined in OpenAPI - - stream_slicers: The stream_slicers of this CartesianProductStreamSlicer. - """ - - stream_slicers: List[AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer] = Field(alias="stream_slicers") - -CartesianProductStreamSlicer.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer_all_of.py deleted file mode 100644 index 4c2c9c750e3cc..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/cartesian_product_stream_slicer_all_of.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_cartesian_product_stream_slicer_datetime_stream_slicer_list_stream_slicer_single_slice_substream_slicer import AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer - - -class CartesianProductStreamSlicerAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CartesianProductStreamSlicerAllOf - a model defined in OpenAPI - - stream_slicers: The stream_slicers of this CartesianProductStreamSlicerAllOf. - """ - - stream_slicers: List[AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer] = Field(alias="stream_slicers") - -CartesianProductStreamSlicerAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/check_stream.py b/airbyte-connector-builder-server/connector_builder/generated/models/check_stream.py deleted file mode 100644 index aa7cfa6b794b0..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/check_stream.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class CheckStream(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CheckStream - a model defined in OpenAPI - - stream_names: The stream_names of this CheckStream. - """ - - stream_names: List[str] = Field(alias="stream_names") - -CheckStream.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler.py b/airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler.py deleted file mode 100644 index 159d8d11403f8..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_composite_error_handler_default_error_handler import AnyOfCompositeErrorHandlerDefaultErrorHandler -from connector_builder.generated.models.composite_error_handler_all_of import CompositeErrorHandlerAllOf - - -class CompositeErrorHandler(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CompositeErrorHandler - a model defined in OpenAPI - - error_handlers: The error_handlers of this CompositeErrorHandler. - """ - - error_handlers: List[AnyOfCompositeErrorHandlerDefaultErrorHandler] = Field(alias="error_handlers") - -CompositeErrorHandler.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler_all_of.py deleted file mode 100644 index a9b8d949b600e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/composite_error_handler_all_of.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_composite_error_handler_default_error_handler import AnyOfCompositeErrorHandlerDefaultErrorHandler - - -class CompositeErrorHandlerAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CompositeErrorHandlerAllOf - a model defined in OpenAPI - - error_handlers: The error_handlers of this CompositeErrorHandlerAllOf. - """ - - error_handlers: List[AnyOfCompositeErrorHandlerDefaultErrorHandler] = Field(alias="error_handlers") - -CompositeErrorHandlerAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/config_component_schema.py b/airbyte-connector-builder-server/connector_builder/generated/models/config_component_schema.py deleted file mode 100644 index 4dd567a444e6a..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/config_component_schema.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.check_stream import CheckStream -from connector_builder.generated.models.declarative_stream import DeclarativeStream - - -class ConfigComponentSchema(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ConfigComponentSchema - a model defined in OpenAPI - - version: The version of this ConfigComponentSchema. - check: The check of this ConfigComponentSchema. - streams: The streams of this ConfigComponentSchema. - """ - - version: str = Field(alias="version") - check: CheckStream = Field(alias="check") - streams: List[DeclarativeStream] = Field(alias="streams") - -ConfigComponentSchema.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/connector_manifest.py b/airbyte-connector-builder-server/connector_builder/generated/models/connector_manifest.py deleted file mode 100644 index 0ef33db0a1e80..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/connector_manifest.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.check_stream import CheckStream -from connector_builder.generated.models.declarative_stream import DeclarativeStream - - -class ConnectorManifest(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ConnectorManifest - a model defined in OpenAPI - - version: The version of this ConnectorManifest. - check: The check of this ConnectorManifest. - streams: The streams of this ConnectorManifest. - """ - - version: str = Field(alias="version") - check: CheckStream = Field(alias="check") - streams: List[DeclarativeStream] = Field(alias="streams") - -ConnectorManifest.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy.py b/airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy.py deleted file mode 100644 index fafdbd2c1055f..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringnumberstring import AnyOfInterpolatedStringnumberstring -from connector_builder.generated.models.constant_backoff_strategy_all_of import ConstantBackoffStrategyAllOf - - -class ConstantBackoffStrategy(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ConstantBackoffStrategy - a model defined in OpenAPI - - backoff_time_in_seconds: The backoff_time_in_seconds of this ConstantBackoffStrategy. - config: The config of this ConstantBackoffStrategy. - """ - - backoff_time_in_seconds: AnyOfInterpolatedStringnumberstring = Field(alias="backoff_time_in_seconds") - config: Dict[str, Any] = Field(alias="config") - -ConstantBackoffStrategy.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy_all_of.py deleted file mode 100644 index 11849c7a2d7f1..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/constant_backoff_strategy_all_of.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringnumberstring import AnyOfInterpolatedStringnumberstring - - -class ConstantBackoffStrategyAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ConstantBackoffStrategyAllOf - a model defined in OpenAPI - - backoff_time_in_seconds: The backoff_time_in_seconds of this ConstantBackoffStrategyAllOf. - config: The config of this ConstantBackoffStrategyAllOf. - """ - - backoff_time_in_seconds: AnyOfInterpolatedStringnumberstring = Field(alias="backoff_time_in_seconds") - config: Dict[str, Any] = Field(alias="config") - -ConstantBackoffStrategyAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy.py b/airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy.py deleted file mode 100644 index e5c1b4e1d22dd..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy.py +++ /dev/null @@ -1,36 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_booleanstring import AnyOfInterpolatedBooleanstring -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.cursor_pagination_strategy_all_of import CursorPaginationStrategyAllOf -from connector_builder.generated.models.json_decoder import JsonDecoder - - -class CursorPaginationStrategy(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CursorPaginationStrategy - a model defined in OpenAPI - - cursor_value: The cursor_value of this CursorPaginationStrategy. - config: The config of this CursorPaginationStrategy. - page_size: The page_size of this CursorPaginationStrategy [Optional]. - stop_condition: The stop_condition of this CursorPaginationStrategy [Optional]. - decoder: The decoder of this CursorPaginationStrategy [Optional]. - """ - - cursor_value: AnyOfInterpolatedStringstring = Field(alias="cursor_value") - config: Dict[str, Any] = Field(alias="config") - page_size: Optional[int] = Field(alias="page_size", default=None) - stop_condition: Optional[AnyOfInterpolatedBooleanstring] = Field(alias="stop_condition", default=None) - decoder: Optional[JsonDecoder] = Field(alias="decoder", default=None) - -CursorPaginationStrategy.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy_all_of.py deleted file mode 100644 index 10281e69e51af..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/cursor_pagination_strategy_all_of.py +++ /dev/null @@ -1,35 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_booleanstring import AnyOfInterpolatedBooleanstring -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.json_decoder import JsonDecoder - - -class CursorPaginationStrategyAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - CursorPaginationStrategyAllOf - a model defined in OpenAPI - - cursor_value: The cursor_value of this CursorPaginationStrategyAllOf. - config: The config of this CursorPaginationStrategyAllOf. - page_size: The page_size of this CursorPaginationStrategyAllOf [Optional]. - stop_condition: The stop_condition of this CursorPaginationStrategyAllOf [Optional]. - decoder: The decoder of this CursorPaginationStrategyAllOf [Optional]. - """ - - cursor_value: AnyOfInterpolatedStringstring = Field(alias="cursor_value") - config: Dict[str, Any] = Field(alias="config") - page_size: Optional[int] = Field(alias="page_size", default=None) - stop_condition: Optional[AnyOfInterpolatedBooleanstring] = Field(alias="stop_condition", default=None) - decoder: Optional[JsonDecoder] = Field(alias="decoder", default=None) - -CursorPaginationStrategyAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer.py b/airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer.py deleted file mode 100644 index 6e752c9c98190..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer.py +++ /dev/null @@ -1,53 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_of_min_max_datetimestring import AnyOfMinMaxDatetimestring -from connector_builder.generated.models.datetime_stream_slicer_all_of import DatetimeStreamSlicerAllOf -from connector_builder.generated.models.request_option import RequestOption -from connector_builder.generated.models.stream_slicer import StreamSlicer - - -class DatetimeStreamSlicer(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DatetimeStreamSlicer - a model defined in OpenAPI - - start_datetime: The start_datetime of this DatetimeStreamSlicer. - end_datetime: The end_datetime of this DatetimeStreamSlicer. - step: The step of this DatetimeStreamSlicer. - cursor_field: The cursor_field of this DatetimeStreamSlicer. - datetime_format: The datetime_format of this DatetimeStreamSlicer. - config: The config of this DatetimeStreamSlicer. - cursor: The cursor of this DatetimeStreamSlicer [Optional]. - cursor_end: The cursor_end of this DatetimeStreamSlicer [Optional]. - start_time_option: The start_time_option of this DatetimeStreamSlicer [Optional]. - end_time_option: The end_time_option of this DatetimeStreamSlicer [Optional]. - stream_state_field_start: The stream_state_field_start of this DatetimeStreamSlicer [Optional]. - stream_state_field_end: The stream_state_field_end of this DatetimeStreamSlicer [Optional]. - lookback_window: The lookback_window of this DatetimeStreamSlicer [Optional]. - """ - - start_datetime: AnyOfMinMaxDatetimestring = Field(alias="start_datetime") - end_datetime: AnyOfMinMaxDatetimestring = Field(alias="end_datetime") - step: str = Field(alias="step") - cursor_field: AnyOfInterpolatedStringstring = Field(alias="cursor_field") - datetime_format: str = Field(alias="datetime_format") - config: Dict[str, Any] = Field(alias="config") - cursor: Optional[Dict[str, Any]] = Field(alias="_cursor", default=None) - cursor_end: Optional[Dict[str, Any]] = Field(alias="_cursor_end", default=None) - start_time_option: Optional[RequestOption] = Field(alias="start_time_option", default=None) - end_time_option: Optional[RequestOption] = Field(alias="end_time_option", default=None) - stream_state_field_start: Optional[str] = Field(alias="stream_state_field_start", default=None) - stream_state_field_end: Optional[str] = Field(alias="stream_state_field_end", default=None) - lookback_window: Optional[AnyOfInterpolatedStringstring] = Field(alias="lookback_window", default=None) - -DatetimeStreamSlicer.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer_all_of.py deleted file mode 100644 index dcd4d06d5fd59..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/datetime_stream_slicer_all_of.py +++ /dev/null @@ -1,51 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_of_min_max_datetimestring import AnyOfMinMaxDatetimestring -from connector_builder.generated.models.request_option import RequestOption - - -class DatetimeStreamSlicerAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DatetimeStreamSlicerAllOf - a model defined in OpenAPI - - start_datetime: The start_datetime of this DatetimeStreamSlicerAllOf. - end_datetime: The end_datetime of this DatetimeStreamSlicerAllOf. - step: The step of this DatetimeStreamSlicerAllOf. - cursor_field: The cursor_field of this DatetimeStreamSlicerAllOf. - datetime_format: The datetime_format of this DatetimeStreamSlicerAllOf. - config: The config of this DatetimeStreamSlicerAllOf. - cursor: The cursor of this DatetimeStreamSlicerAllOf [Optional]. - cursor_end: The cursor_end of this DatetimeStreamSlicerAllOf [Optional]. - start_time_option: The start_time_option of this DatetimeStreamSlicerAllOf [Optional]. - end_time_option: The end_time_option of this DatetimeStreamSlicerAllOf [Optional]. - stream_state_field_start: The stream_state_field_start of this DatetimeStreamSlicerAllOf [Optional]. - stream_state_field_end: The stream_state_field_end of this DatetimeStreamSlicerAllOf [Optional]. - lookback_window: The lookback_window of this DatetimeStreamSlicerAllOf [Optional]. - """ - - start_datetime: AnyOfMinMaxDatetimestring = Field(alias="start_datetime") - end_datetime: AnyOfMinMaxDatetimestring = Field(alias="end_datetime") - step: str = Field(alias="step") - cursor_field: AnyOfInterpolatedStringstring = Field(alias="cursor_field") - datetime_format: str = Field(alias="datetime_format") - config: Dict[str, Any] = Field(alias="config") - cursor: Optional[Dict[str, Any]] = Field(alias="_cursor", default=None) - cursor_end: Optional[Dict[str, Any]] = Field(alias="_cursor_end", default=None) - start_time_option: Optional[RequestOption] = Field(alias="start_time_option", default=None) - end_time_option: Optional[RequestOption] = Field(alias="end_time_option", default=None) - stream_state_field_start: Optional[str] = Field(alias="stream_state_field_start", default=None) - stream_state_field_end: Optional[str] = Field(alias="stream_state_field_end", default=None) - lookback_window: Optional[AnyOfInterpolatedStringstring] = Field(alias="lookback_window", default=None) - -DatetimeStreamSlicerAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator.py b/airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator.py deleted file mode 100644 index e027ed33a7d45..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator.py +++ /dev/null @@ -1,48 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.declarative_oauth2_authenticator_all_of import DeclarativeOauth2AuthenticatorAllOf - - -class DeclarativeOauth2Authenticator(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DeclarativeOauth2Authenticator - a model defined in OpenAPI - - token_refresh_endpoint: The token_refresh_endpoint of this DeclarativeOauth2Authenticator. - client_id: The client_id of this DeclarativeOauth2Authenticator. - client_secret: The client_secret of this DeclarativeOauth2Authenticator. - refresh_token: The refresh_token of this DeclarativeOauth2Authenticator. - config: The config of this DeclarativeOauth2Authenticator. - scopes: The scopes of this DeclarativeOauth2Authenticator [Optional]. - token_expiry_date: The token_expiry_date of this DeclarativeOauth2Authenticator [Optional]. - token_expiry_date: The token_expiry_date of this DeclarativeOauth2Authenticator [Optional]. - access_token_name: The access_token_name of this DeclarativeOauth2Authenticator [Optional]. - expires_in_name: The expires_in_name of this DeclarativeOauth2Authenticator [Optional]. - refresh_request_body: The refresh_request_body of this DeclarativeOauth2Authenticator [Optional]. - grant_type: The grant_type of this DeclarativeOauth2Authenticator [Optional]. - """ - - token_refresh_endpoint: AnyOfInterpolatedStringstring = Field(alias="token_refresh_endpoint") - client_id: AnyOfInterpolatedStringstring = Field(alias="client_id") - client_secret: AnyOfInterpolatedStringstring = Field(alias="client_secret") - refresh_token: AnyOfInterpolatedStringstring = Field(alias="refresh_token") - config: Dict[str, Any] = Field(alias="config") - scopes: Optional[List[str]] = Field(alias="scopes", default=None) - token_expiry_date: Optional[AnyOfInterpolatedStringstring] = Field(alias="token_expiry_date", default=None) - token_expiry_date: Optional[object] = Field(alias="_token_expiry_date", default=None) - access_token_name: Optional[AnyOfInterpolatedStringstring] = Field(alias="access_token_name", default=None) - expires_in_name: Optional[AnyOfInterpolatedStringstring] = Field(alias="expires_in_name", default=None) - refresh_request_body: Optional[Dict[str, Any]] = Field(alias="refresh_request_body", default=None) - grant_type: Optional[AnyOfInterpolatedStringstring] = Field(alias="grant_type", default=None) - -DeclarativeOauth2Authenticator.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator_all_of.py deleted file mode 100644 index 1b8d2820b0528..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/declarative_oauth2_authenticator_all_of.py +++ /dev/null @@ -1,47 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class DeclarativeOauth2AuthenticatorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DeclarativeOauth2AuthenticatorAllOf - a model defined in OpenAPI - - token_refresh_endpoint: The token_refresh_endpoint of this DeclarativeOauth2AuthenticatorAllOf. - client_id: The client_id of this DeclarativeOauth2AuthenticatorAllOf. - client_secret: The client_secret of this DeclarativeOauth2AuthenticatorAllOf. - refresh_token: The refresh_token of this DeclarativeOauth2AuthenticatorAllOf. - config: The config of this DeclarativeOauth2AuthenticatorAllOf. - scopes: The scopes of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - token_expiry_date: The token_expiry_date of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - token_expiry_date: The token_expiry_date of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - access_token_name: The access_token_name of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - expires_in_name: The expires_in_name of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - refresh_request_body: The refresh_request_body of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - grant_type: The grant_type of this DeclarativeOauth2AuthenticatorAllOf [Optional]. - """ - - token_refresh_endpoint: AnyOfInterpolatedStringstring = Field(alias="token_refresh_endpoint") - client_id: AnyOfInterpolatedStringstring = Field(alias="client_id") - client_secret: AnyOfInterpolatedStringstring = Field(alias="client_secret") - refresh_token: AnyOfInterpolatedStringstring = Field(alias="refresh_token") - config: Dict[str, Any] = Field(alias="config") - scopes: Optional[List[str]] = Field(alias="scopes", default=None) - token_expiry_date: Optional[AnyOfInterpolatedStringstring] = Field(alias="token_expiry_date", default=None) - token_expiry_date: Optional[object] = Field(alias="_token_expiry_date", default=None) - access_token_name: Optional[AnyOfInterpolatedStringstring] = Field(alias="access_token_name", default=None) - expires_in_name: Optional[AnyOfInterpolatedStringstring] = Field(alias="expires_in_name", default=None) - refresh_request_body: Optional[Dict[str, Any]] = Field(alias="refresh_request_body", default=None) - grant_type: Optional[AnyOfInterpolatedStringstring] = Field(alias="grant_type", default=None) - -DeclarativeOauth2AuthenticatorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/declarative_stream.py b/airbyte-connector-builder-server/connector_builder/generated/models/declarative_stream.py deleted file mode 100644 index 0ae815717dbee..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/declarative_stream.py +++ /dev/null @@ -1,49 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_add_fields_remove_fields import AnyOfAddFieldsRemoveFields -from connector_builder.generated.models.any_of_json_file_schema_loader_default_schema_loader import AnyOfJsonFileSchemaLoaderDefaultSchemaLoader -from connector_builder.generated.models.any_ofarrayarraystring import AnyOfarrayarraystring -from connector_builder.generated.models.any_ofarraystring import AnyOfarraystring -from connector_builder.generated.models.simple_retriever import SimpleRetriever - - -class DeclarativeStream(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DeclarativeStream - a model defined in OpenAPI - - retriever: The retriever of this DeclarativeStream. - config: The config of this DeclarativeStream. - name: The name of this DeclarativeStream [Optional]. - primary_key: The primary_key of this DeclarativeStream [Optional]. - schema_loader: The schema_loader of this DeclarativeStream [Optional]. - name: The name of this DeclarativeStream [Optional]. - primary_key: The primary_key of this DeclarativeStream [Optional]. - schema_loader: The schema_loader of this DeclarativeStream [Optional]. - stream_cursor_field: The stream_cursor_field of this DeclarativeStream [Optional]. - transformations: The transformations of this DeclarativeStream [Optional]. - checkpoint_interval: The checkpoint_interval of this DeclarativeStream [Optional]. - """ - - retriever: SimpleRetriever = Field(alias="retriever") - config: Dict[str, Any] = Field(alias="config") - name: Optional[str] = Field(alias="name", default=None) - primary_key: Optional[AnyOfarrayarraystring] = Field(alias="primary_key", default=None) - schema_loader: Optional[AnyOfJsonFileSchemaLoaderDefaultSchemaLoader] = Field(alias="schema_loader", default=None) - name: Optional[str] = Field(alias="_name", default=None) - primary_key: Optional[str] = Field(alias="_primary_key", default=None) - schema_loader: Optional[AnyOfJsonFileSchemaLoaderDefaultSchemaLoader] = Field(alias="_schema_loader", default=None) - stream_cursor_field: Optional[AnyOfarraystring] = Field(alias="stream_cursor_field", default=None) - transformations: Optional[List[AnyOfAddFieldsRemoveFields]] = Field(alias="transformations", default=None) - checkpoint_interval: Optional[int] = Field(alias="checkpoint_interval", default=None) - -DeclarativeStream.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler.py b/airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler.py deleted file mode 100644 index 374308d1060f0..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler.py +++ /dev/null @@ -1,35 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_constant_backoff_strategy_exponential_backoff_strategy_wait_time_from_header_backoff_strategy_wait_until_time_from_header_backoff_strategy import AnyOfConstantBackoffStrategyExponentialBackoffStrategyWaitTimeFromHeaderBackoffStrategyWaitUntilTimeFromHeaderBackoffStrategy -from connector_builder.generated.models.default_error_handler_all_of import DefaultErrorHandlerAllOf -from connector_builder.generated.models.http_response_filter import HttpResponseFilter - - -class DefaultErrorHandler(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DefaultErrorHandler - a model defined in OpenAPI - - config: The config of this DefaultErrorHandler. - response_filters: The response_filters of this DefaultErrorHandler [Optional]. - max_retries: The max_retries of this DefaultErrorHandler [Optional]. - max_retries: The max_retries of this DefaultErrorHandler [Optional]. - backoff_strategies: The backoff_strategies of this DefaultErrorHandler [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - response_filters: Optional[List[HttpResponseFilter]] = Field(alias="response_filters", default=None) - max_retries: Optional[int] = Field(alias="max_retries", default=None) - max_retries: Optional[int] = Field(alias="_max_retries", default=None) - backoff_strategies: Optional[List[AnyOfConstantBackoffStrategyExponentialBackoffStrategyWaitTimeFromHeaderBackoffStrategyWaitUntilTimeFromHeaderBackoffStrategy]] = Field(alias="backoff_strategies", default=None) - -DefaultErrorHandler.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler_all_of.py deleted file mode 100644 index 4179e5b1fa66e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/default_error_handler_all_of.py +++ /dev/null @@ -1,34 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_constant_backoff_strategy_exponential_backoff_strategy_wait_time_from_header_backoff_strategy_wait_until_time_from_header_backoff_strategy import AnyOfConstantBackoffStrategyExponentialBackoffStrategyWaitTimeFromHeaderBackoffStrategyWaitUntilTimeFromHeaderBackoffStrategy -from connector_builder.generated.models.http_response_filter import HttpResponseFilter - - -class DefaultErrorHandlerAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DefaultErrorHandlerAllOf - a model defined in OpenAPI - - config: The config of this DefaultErrorHandlerAllOf. - response_filters: The response_filters of this DefaultErrorHandlerAllOf [Optional]. - max_retries: The max_retries of this DefaultErrorHandlerAllOf [Optional]. - max_retries: The max_retries of this DefaultErrorHandlerAllOf [Optional]. - backoff_strategies: The backoff_strategies of this DefaultErrorHandlerAllOf [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - response_filters: Optional[List[HttpResponseFilter]] = Field(alias="response_filters", default=None) - max_retries: Optional[int] = Field(alias="max_retries", default=None) - max_retries: Optional[int] = Field(alias="_max_retries", default=None) - backoff_strategies: Optional[List[AnyOfConstantBackoffStrategyExponentialBackoffStrategyWaitTimeFromHeaderBackoffStrategyWaitUntilTimeFromHeaderBackoffStrategy]] = Field(alias="backoff_strategies", default=None) - -DefaultErrorHandlerAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/default_paginator.py b/airbyte-connector-builder-server/connector_builder/generated/models/default_paginator.py deleted file mode 100644 index 375e1c572b49e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/default_paginator.py +++ /dev/null @@ -1,42 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_cursor_pagination_strategy_offset_increment_page_increment import AnyOfCursorPaginationStrategyOffsetIncrementPageIncrement -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.default_paginator_all_of import DefaultPaginatorAllOf -from connector_builder.generated.models.json_decoder import JsonDecoder -from connector_builder.generated.models.paginator import Paginator -from connector_builder.generated.models.request_option import RequestOption - - -class DefaultPaginator(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DefaultPaginator - a model defined in OpenAPI - - pagination_strategy: The pagination_strategy of this DefaultPaginator. - config: The config of this DefaultPaginator. - url_base: The url_base of this DefaultPaginator. - decoder: The decoder of this DefaultPaginator [Optional]. - token: The token of this DefaultPaginator [Optional]. - page_size_option: The page_size_option of this DefaultPaginator [Optional]. - page_token_option: The page_token_option of this DefaultPaginator [Optional]. - """ - - pagination_strategy: AnyOfCursorPaginationStrategyOffsetIncrementPageIncrement = Field(alias="pagination_strategy") - config: Dict[str, Any] = Field(alias="config") - url_base: AnyOfInterpolatedStringstring = Field(alias="url_base") - decoder: Optional[JsonDecoder] = Field(alias="decoder", default=None) - token: Optional[object] = Field(alias="_token", default=None) - page_size_option: Optional[RequestOption] = Field(alias="page_size_option", default=None) - page_token_option: Optional[RequestOption] = Field(alias="page_token_option", default=None) - -DefaultPaginator.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/default_paginator_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/default_paginator_all_of.py deleted file mode 100644 index d683a54cb4b8d..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/default_paginator_all_of.py +++ /dev/null @@ -1,40 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_cursor_pagination_strategy_offset_increment_page_increment import AnyOfCursorPaginationStrategyOffsetIncrementPageIncrement -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.json_decoder import JsonDecoder -from connector_builder.generated.models.request_option import RequestOption - - -class DefaultPaginatorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DefaultPaginatorAllOf - a model defined in OpenAPI - - pagination_strategy: The pagination_strategy of this DefaultPaginatorAllOf. - config: The config of this DefaultPaginatorAllOf. - url_base: The url_base of this DefaultPaginatorAllOf. - decoder: The decoder of this DefaultPaginatorAllOf [Optional]. - token: The token of this DefaultPaginatorAllOf [Optional]. - page_size_option: The page_size_option of this DefaultPaginatorAllOf [Optional]. - page_token_option: The page_token_option of this DefaultPaginatorAllOf [Optional]. - """ - - pagination_strategy: AnyOfCursorPaginationStrategyOffsetIncrementPageIncrement = Field(alias="pagination_strategy") - config: Dict[str, Any] = Field(alias="config") - url_base: AnyOfInterpolatedStringstring = Field(alias="url_base") - decoder: Optional[JsonDecoder] = Field(alias="decoder", default=None) - token: Optional[object] = Field(alias="_token", default=None) - page_size_option: Optional[RequestOption] = Field(alias="page_size_option", default=None) - page_token_option: Optional[RequestOption] = Field(alias="page_token_option", default=None) - -DefaultPaginatorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader.py b/airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader.py deleted file mode 100644 index fc431f1eebbef..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.default_schema_loader_all_of import DefaultSchemaLoaderAllOf - - -class DefaultSchemaLoader(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DefaultSchemaLoader - a model defined in OpenAPI - - config: The config of this DefaultSchemaLoader. - """ - - config: Dict[str, Any] = Field(alias="config") - -DefaultSchemaLoader.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader_all_of.py deleted file mode 100644 index 8e753d9bcb7ca..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/default_schema_loader_all_of.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class DefaultSchemaLoaderAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DefaultSchemaLoaderAllOf - a model defined in OpenAPI - - config: The config of this DefaultSchemaLoaderAllOf. - """ - - config: Dict[str, Any] = Field(alias="config") - -DefaultSchemaLoaderAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor.py b/airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor.py deleted file mode 100644 index 86bb8f6145fd1..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor.py +++ /dev/null @@ -1,31 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.dpath_extractor_all_of import DpathExtractorAllOf -from connector_builder.generated.models.json_decoder import JsonDecoder - - -class DpathExtractor(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DpathExtractor - a model defined in OpenAPI - - field_pointer: The field_pointer of this DpathExtractor. - config: The config of this DpathExtractor. - decoder: The decoder of this DpathExtractor [Optional]. - """ - - field_pointer: List[AnyOfInterpolatedStringstring] = Field(alias="field_pointer") - config: Dict[str, Any] = Field(alias="config") - decoder: Optional[JsonDecoder] = Field(alias="decoder", default=None) - -DpathExtractor.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor_all_of.py deleted file mode 100644 index 9e7b152be5304..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/dpath_extractor_all_of.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.json_decoder import JsonDecoder - - -class DpathExtractorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - DpathExtractorAllOf - a model defined in OpenAPI - - field_pointer: The field_pointer of this DpathExtractorAllOf. - config: The config of this DpathExtractorAllOf. - decoder: The decoder of this DpathExtractorAllOf [Optional]. - """ - - field_pointer: List[AnyOfInterpolatedStringstring] = Field(alias="field_pointer") - config: Dict[str, Any] = Field(alias="config") - decoder: Optional[JsonDecoder] = Field(alias="decoder", default=None) - -DpathExtractorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy.py b/airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy.py deleted file mode 100644 index 551ef4562591f..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringnumberstring import AnyOfInterpolatedStringnumberstring -from connector_builder.generated.models.exponential_backoff_strategy_all_of import ExponentialBackoffStrategyAllOf - - -class ExponentialBackoffStrategy(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ExponentialBackoffStrategy - a model defined in OpenAPI - - config: The config of this ExponentialBackoffStrategy. - factor: The factor of this ExponentialBackoffStrategy [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - factor: Optional[AnyOfInterpolatedStringnumberstring] = Field(alias="factor", default=None) - -ExponentialBackoffStrategy.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy_all_of.py deleted file mode 100644 index d2c26b9321a2c..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/exponential_backoff_strategy_all_of.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringnumberstring import AnyOfInterpolatedStringnumberstring - - -class ExponentialBackoffStrategyAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ExponentialBackoffStrategyAllOf - a model defined in OpenAPI - - config: The config of this ExponentialBackoffStrategyAllOf. - factor: The factor of this ExponentialBackoffStrategyAllOf [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - factor: Optional[AnyOfInterpolatedStringnumberstring] = Field(alias="factor", default=None) - -ExponentialBackoffStrategyAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/extra_models.py b/airbyte-connector-builder-server/connector_builder/generated/models/extra_models.py deleted file mode 100644 index a3a283fb842b3..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/extra_models.py +++ /dev/null @@ -1,8 +0,0 @@ -# coding: utf-8 - -from pydantic import BaseModel - -class TokenModel(BaseModel): - """Defines a token model.""" - - sub: str diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/http_request.py b/airbyte-connector-builder-server/connector_builder/generated/models/http_request.py deleted file mode 100644 index 5f29b9d0b7c54..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/http_request.py +++ /dev/null @@ -1,32 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class HttpRequest(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - HttpRequest - a model defined in OpenAPI - - url: The url of this HttpRequest. - parameters: The parameters of this HttpRequest [Optional]. - body: The body of this HttpRequest [Optional]. - headers: The headers of this HttpRequest [Optional]. - http_method: The http_method of this HttpRequest. - """ - - url: str - parameters: Optional[Dict[str, Any]] = None - body: Optional[Dict[str, Any]] = None - headers: Optional[Dict[str, Any]] = None - http_method: str - -HttpRequest.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/http_requester.py b/airbyte-connector-builder-server/connector_builder/generated/models/http_requester.py deleted file mode 100644 index bf4be60005cdb..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/http_requester.py +++ /dev/null @@ -1,45 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_composite_error_handler_default_error_handler import AnyOfCompositeErrorHandlerDefaultErrorHandler -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_of_no_auth_declarative_oauth2_authenticator_api_key_authenticator_bearer_authenticator_basic_http_authenticator import AnyOfNoAuthDeclarativeOauth2AuthenticatorApiKeyAuthenticatorBearerAuthenticatorBasicHttpAuthenticator -from connector_builder.generated.models.any_ofstringstring import AnyOfstringstring -from connector_builder.generated.models.http_requester_all_of import HttpRequesterAllOf -from connector_builder.generated.models.interpolated_request_options_provider import InterpolatedRequestOptionsProvider -from connector_builder.generated.models.requester import Requester - - -class HttpRequester(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - HttpRequester - a model defined in OpenAPI - - name: The name of this HttpRequester. - url_base: The url_base of this HttpRequester. - path: The path of this HttpRequester. - config: The config of this HttpRequester. - http_method: The http_method of this HttpRequester [Optional]. - request_options_provider: The request_options_provider of this HttpRequester [Optional]. - authenticator: The authenticator of this HttpRequester [Optional]. - error_handler: The error_handler of this HttpRequester [Optional]. - """ - - name: str = Field(alias="name") - url_base: AnyOfInterpolatedStringstring = Field(alias="url_base") - path: AnyOfInterpolatedStringstring = Field(alias="path") - config: Dict[str, Any] = Field(alias="config") - http_method: Optional[AnyOfstringstring] = Field(alias="http_method", default=None) - request_options_provider: Optional[InterpolatedRequestOptionsProvider] = Field(alias="request_options_provider", default=None) - authenticator: Optional[AnyOfNoAuthDeclarativeOauth2AuthenticatorApiKeyAuthenticatorBearerAuthenticatorBasicHttpAuthenticator] = Field(alias="authenticator", default=None) - error_handler: Optional[AnyOfCompositeErrorHandlerDefaultErrorHandler] = Field(alias="error_handler", default=None) - -HttpRequester.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/http_requester_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/http_requester_all_of.py deleted file mode 100644 index 7f2a42e36b6f7..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/http_requester_all_of.py +++ /dev/null @@ -1,43 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_composite_error_handler_default_error_handler import AnyOfCompositeErrorHandlerDefaultErrorHandler -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_of_no_auth_declarative_oauth2_authenticator_api_key_authenticator_bearer_authenticator_basic_http_authenticator import AnyOfNoAuthDeclarativeOauth2AuthenticatorApiKeyAuthenticatorBearerAuthenticatorBasicHttpAuthenticator -from connector_builder.generated.models.any_ofstringstring import AnyOfstringstring -from connector_builder.generated.models.interpolated_request_options_provider import InterpolatedRequestOptionsProvider - - -class HttpRequesterAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - HttpRequesterAllOf - a model defined in OpenAPI - - name: The name of this HttpRequesterAllOf. - url_base: The url_base of this HttpRequesterAllOf. - path: The path of this HttpRequesterAllOf. - config: The config of this HttpRequesterAllOf. - http_method: The http_method of this HttpRequesterAllOf [Optional]. - request_options_provider: The request_options_provider of this HttpRequesterAllOf [Optional]. - authenticator: The authenticator of this HttpRequesterAllOf [Optional]. - error_handler: The error_handler of this HttpRequesterAllOf [Optional]. - """ - - name: str = Field(alias="name") - url_base: AnyOfInterpolatedStringstring = Field(alias="url_base") - path: AnyOfInterpolatedStringstring = Field(alias="path") - config: Dict[str, Any] = Field(alias="config") - http_method: Optional[AnyOfstringstring] = Field(alias="http_method", default=None) - request_options_provider: Optional[InterpolatedRequestOptionsProvider] = Field(alias="request_options_provider", default=None) - authenticator: Optional[AnyOfNoAuthDeclarativeOauth2AuthenticatorApiKeyAuthenticatorBearerAuthenticatorBasicHttpAuthenticator] = Field(alias="authenticator", default=None) - error_handler: Optional[AnyOfCompositeErrorHandlerDefaultErrorHandler] = Field(alias="error_handler", default=None) - -HttpRequesterAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/http_response.py b/airbyte-connector-builder-server/connector_builder/generated/models/http_response.py deleted file mode 100644 index 49a81ebeb628d..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/http_response.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class HttpResponse(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - HttpResponse - a model defined in OpenAPI - - status: The status of this HttpResponse. - body: The body of this HttpResponse [Optional]. - headers: The headers of this HttpResponse [Optional]. - """ - - status: int - body: Optional[Dict[str, Any]] = None - headers: Optional[Dict[str, Any]] = None - -HttpResponse.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/http_response_filter.py b/airbyte-connector-builder-server/connector_builder/generated/models/http_response_filter.py deleted file mode 100644 index 8440949d7c268..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/http_response_filter.py +++ /dev/null @@ -1,37 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_booleanstring import AnyOfInterpolatedBooleanstring -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_ofstringstring import AnyOfstringstring - - -class HttpResponseFilter(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - HttpResponseFilter - a model defined in OpenAPI - - action: The action of this HttpResponseFilter. - config: The config of this HttpResponseFilter. - http_codes: The http_codes of this HttpResponseFilter [Optional]. - error_message_contains: The error_message_contains of this HttpResponseFilter [Optional]. - predicate: The predicate of this HttpResponseFilter [Optional]. - error_message: The error_message of this HttpResponseFilter [Optional]. - """ - - action: AnyOfstringstring = Field(alias="action") - config: Dict[str, Any] = Field(alias="config") - http_codes: Optional[list[int]] = Field(alias="http_codes", default=None) - error_message_contains: Optional[str] = Field(alias="error_message_contains", default=None) - predicate: Optional[AnyOfInterpolatedBooleanstring] = Field(alias="predicate", default=None) - error_message: Optional[AnyOfInterpolatedStringstring] = Field(alias="error_message", default=None) - -HttpResponseFilter.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_boolean.py b/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_boolean.py deleted file mode 100644 index 4c50980fec094..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_boolean.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class InterpolatedBoolean(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - InterpolatedBoolean - a model defined in OpenAPI - - condition: The condition of this InterpolatedBoolean. - """ - - condition: str = Field(alias="condition") - -InterpolatedBoolean.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider.py b/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider.py deleted file mode 100644 index 7a8a9afbff0c9..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider.py +++ /dev/null @@ -1,34 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_ofmapstring import AnyOfmapstring -from connector_builder.generated.models.interpolated_request_options_provider_all_of import InterpolatedRequestOptionsProviderAllOf - - -class InterpolatedRequestOptionsProvider(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - InterpolatedRequestOptionsProvider - a model defined in OpenAPI - - config: The config of this InterpolatedRequestOptionsProvider [Optional]. - request_parameters: The request_parameters of this InterpolatedRequestOptionsProvider [Optional]. - request_headers: The request_headers of this InterpolatedRequestOptionsProvider [Optional]. - request_body_data: The request_body_data of this InterpolatedRequestOptionsProvider [Optional]. - request_body_json: The request_body_json of this InterpolatedRequestOptionsProvider [Optional]. - """ - - config: Optional[Dict[str, Any]] = Field(alias="config", default=None) - request_parameters: Optional[AnyOfmapstring] = Field(alias="request_parameters", default=None) - request_headers: Optional[AnyOfmapstring] = Field(alias="request_headers", default=None) - request_body_data: Optional[AnyOfmapstring] = Field(alias="request_body_data", default=None) - request_body_json: Optional[AnyOfmapstring] = Field(alias="request_body_json", default=None) - -InterpolatedRequestOptionsProvider.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider_all_of.py deleted file mode 100644 index 3958af7231c53..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_request_options_provider_all_of.py +++ /dev/null @@ -1,33 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_ofmapstring import AnyOfmapstring - - -class InterpolatedRequestOptionsProviderAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - InterpolatedRequestOptionsProviderAllOf - a model defined in OpenAPI - - config: The config of this InterpolatedRequestOptionsProviderAllOf [Optional]. - request_parameters: The request_parameters of this InterpolatedRequestOptionsProviderAllOf [Optional]. - request_headers: The request_headers of this InterpolatedRequestOptionsProviderAllOf [Optional]. - request_body_data: The request_body_data of this InterpolatedRequestOptionsProviderAllOf [Optional]. - request_body_json: The request_body_json of this InterpolatedRequestOptionsProviderAllOf [Optional]. - """ - - config: Optional[Dict[str, Any]] = Field(alias="config", default=None) - request_parameters: Optional[AnyOfmapstring] = Field(alias="request_parameters", default=None) - request_headers: Optional[AnyOfmapstring] = Field(alias="request_headers", default=None) - request_body_data: Optional[AnyOfmapstring] = Field(alias="request_body_data", default=None) - request_body_json: Optional[AnyOfmapstring] = Field(alias="request_body_json", default=None) - -InterpolatedRequestOptionsProviderAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_string.py b/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_string.py deleted file mode 100644 index f202e9f19f22e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/interpolated_string.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class InterpolatedString(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - InterpolatedString - a model defined in OpenAPI - - string: The string of this InterpolatedString. - default: The default of this InterpolatedString [Optional]. - """ - - string: str = Field(alias="string") - default: Optional[str] = Field(alias="default", default=None) - -InterpolatedString.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_exception_info.py b/airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_exception_info.py deleted file mode 100644 index 878690e098259..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_exception_info.py +++ /dev/null @@ -1,31 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 -from connector_builder.generated.models.invalid_input_property import InvalidInputProperty - - -class InvalidInputExceptionInfo(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - InvalidInputExceptionInfo - a model defined in OpenAPI - - message: The message of this InvalidInputExceptionInfo. - exception_class_name: The exception_class_name of this InvalidInputExceptionInfo [Optional]. - exception_stack: The exception_stack of this InvalidInputExceptionInfo [Optional]. - validation_errors: The validation_errors of this InvalidInputExceptionInfo. - """ - - message: str - exception_class_name: Optional[str] = None - exception_stack: Optional[List[str]] = None - validation_errors: List[InvalidInputProperty] - -InvalidInputExceptionInfo.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_property.py b/airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_property.py deleted file mode 100644 index 35e17c1120901..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/invalid_input_property.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class InvalidInputProperty(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - InvalidInputProperty - a model defined in OpenAPI - - property_path: The property_path of this InvalidInputProperty. - invalid_value: The invalid_value of this InvalidInputProperty [Optional]. - message: The message of this InvalidInputProperty [Optional]. - """ - - property_path: str - invalid_value: Optional[str] = None - message: Optional[str] = None - -InvalidInputProperty.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/json_decoder.py b/airbyte-connector-builder-server/connector_builder/generated/models/json_decoder.py deleted file mode 100644 index cfb540e19c7ce..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/json_decoder.py +++ /dev/null @@ -1,22 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class JsonDecoder(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - JsonDecoder - a model defined in OpenAPI - - """ - - -JsonDecoder.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader.py b/airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader.py deleted file mode 100644 index 2e2dd066caa9e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.json_file_schema_loader_all_of import JsonFileSchemaLoaderAllOf - - -class JsonFileSchemaLoader(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - JsonFileSchemaLoader - a model defined in OpenAPI - - config: The config of this JsonFileSchemaLoader. - file_path: The file_path of this JsonFileSchemaLoader [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - file_path: Optional[AnyOfInterpolatedStringstring] = Field(alias="file_path", default=None) - -JsonFileSchemaLoader.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader_all_of.py deleted file mode 100644 index 608fedfe17420..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/json_file_schema_loader_all_of.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class JsonFileSchemaLoaderAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - JsonFileSchemaLoaderAllOf - a model defined in OpenAPI - - config: The config of this JsonFileSchemaLoaderAllOf. - file_path: The file_path of this JsonFileSchemaLoaderAllOf [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - file_path: Optional[AnyOfInterpolatedStringstring] = Field(alias="file_path", default=None) - -JsonFileSchemaLoaderAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/known_exception_info.py b/airbyte-connector-builder-server/connector_builder/generated/models/known_exception_info.py deleted file mode 100644 index d349fddc9cb57..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/known_exception_info.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class KnownExceptionInfo(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - KnownExceptionInfo - a model defined in OpenAPI - - message: The message of this KnownExceptionInfo. - exception_class_name: The exception_class_name of this KnownExceptionInfo [Optional]. - exception_stack: The exception_stack of this KnownExceptionInfo [Optional]. - """ - - message: str - exception_class_name: Optional[str] = None - exception_stack: Optional[List[str]] = None - -KnownExceptionInfo.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer.py b/airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer.py deleted file mode 100644 index bf8d576aecc81..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer.py +++ /dev/null @@ -1,35 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_ofarraystring import AnyOfarraystring -from connector_builder.generated.models.list_stream_slicer_all_of import ListStreamSlicerAllOf -from connector_builder.generated.models.request_option import RequestOption -from connector_builder.generated.models.stream_slicer import StreamSlicer - - -class ListStreamSlicer(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ListStreamSlicer - a model defined in OpenAPI - - slice_values: The slice_values of this ListStreamSlicer. - cursor_field: The cursor_field of this ListStreamSlicer. - config: The config of this ListStreamSlicer. - request_option: The request_option of this ListStreamSlicer [Optional]. - """ - - slice_values: AnyOfarraystring = Field(alias="slice_values") - cursor_field: AnyOfInterpolatedStringstring = Field(alias="cursor_field") - config: Dict[str, Any] = Field(alias="config") - request_option: Optional[RequestOption] = Field(alias="request_option", default=None) - -ListStreamSlicer.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer_all_of.py deleted file mode 100644 index be3b00d97dd09..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/list_stream_slicer_all_of.py +++ /dev/null @@ -1,33 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_ofarraystring import AnyOfarraystring -from connector_builder.generated.models.request_option import RequestOption - - -class ListStreamSlicerAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ListStreamSlicerAllOf - a model defined in OpenAPI - - slice_values: The slice_values of this ListStreamSlicerAllOf. - cursor_field: The cursor_field of this ListStreamSlicerAllOf. - config: The config of this ListStreamSlicerAllOf. - request_option: The request_option of this ListStreamSlicerAllOf [Optional]. - """ - - slice_values: AnyOfarraystring = Field(alias="slice_values") - cursor_field: AnyOfInterpolatedStringstring = Field(alias="cursor_field") - config: Dict[str, Any] = Field(alias="config") - request_option: Optional[RequestOption] = Field(alias="request_option", default=None) - -ListStreamSlicerAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/min_max_datetime.py b/airbyte-connector-builder-server/connector_builder/generated/models/min_max_datetime.py deleted file mode 100644 index 074e9adb17ff9..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/min_max_datetime.py +++ /dev/null @@ -1,33 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class MinMaxDatetime(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - MinMaxDatetime - a model defined in OpenAPI - - datetime: The datetime of this MinMaxDatetime. - datetime_format: The datetime_format of this MinMaxDatetime [Optional]. - datetime_format: The datetime_format of this MinMaxDatetime [Optional]. - min_datetime: The min_datetime of this MinMaxDatetime [Optional]. - max_datetime: The max_datetime of this MinMaxDatetime [Optional]. - """ - - datetime: AnyOfInterpolatedStringstring = Field(alias="datetime") - datetime_format: Optional[str] = Field(alias="datetime_format", default=None) - datetime_format: Optional[str] = Field(alias="_datetime_format", default=None) - min_datetime: Optional[AnyOfInterpolatedStringstring] = Field(alias="min_datetime", default=None) - max_datetime: Optional[AnyOfInterpolatedStringstring] = Field(alias="max_datetime", default=None) - -MinMaxDatetime.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/no_auth.py b/airbyte-connector-builder-server/connector_builder/generated/models/no_auth.py deleted file mode 100644 index 79d9cad7ace40..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/no_auth.py +++ /dev/null @@ -1,22 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class NoAuth(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - NoAuth - a model defined in OpenAPI - - """ - - -NoAuth.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/no_pagination.py b/airbyte-connector-builder-server/connector_builder/generated/models/no_pagination.py deleted file mode 100644 index ee4c2303efb9a..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/no_pagination.py +++ /dev/null @@ -1,23 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.paginator import Paginator - - -class NoPagination(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - NoPagination - a model defined in OpenAPI - - """ - - -NoPagination.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/offset_increment.py b/airbyte-connector-builder-server/connector_builder/generated/models/offset_increment.py deleted file mode 100644 index 8c8e719fc553f..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/offset_increment.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.offset_increment_all_of import OffsetIncrementAllOf - - -class OffsetIncrement(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - OffsetIncrement - a model defined in OpenAPI - - page_size: The page_size of this OffsetIncrement. - """ - - page_size: int = Field(alias="page_size") - -OffsetIncrement.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/offset_increment_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/offset_increment_all_of.py deleted file mode 100644 index 3e3e799b73c78..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/offset_increment_all_of.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class OffsetIncrementAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - OffsetIncrementAllOf - a model defined in OpenAPI - - page_size: The page_size of this OffsetIncrementAllOf. - """ - - page_size: int = Field(alias="page_size") - -OffsetIncrementAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/page_increment.py b/airbyte-connector-builder-server/connector_builder/generated/models/page_increment.py deleted file mode 100644 index 0b366c690dc6c..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/page_increment.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.page_increment_all_of import PageIncrementAllOf - - -class PageIncrement(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - PageIncrement - a model defined in OpenAPI - - page_size: The page_size of this PageIncrement. - start_from_page: The start_from_page of this PageIncrement [Optional]. - """ - - page_size: int = Field(alias="page_size") - start_from_page: Optional[int] = Field(alias="start_from_page", default=None) - -PageIncrement.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/page_increment_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/page_increment_all_of.py deleted file mode 100644 index 2276244db68b8..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/page_increment_all_of.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class PageIncrementAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - PageIncrementAllOf - a model defined in OpenAPI - - page_size: The page_size of this PageIncrementAllOf. - start_from_page: The start_from_page of this PageIncrementAllOf [Optional]. - """ - - page_size: int = Field(alias="page_size") - start_from_page: Optional[int] = Field(alias="start_from_page", default=None) - -PageIncrementAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/paginator.py b/airbyte-connector-builder-server/connector_builder/generated/models/paginator.py deleted file mode 100644 index 735e4e849d17c..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/paginator.py +++ /dev/null @@ -1,22 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class Paginator(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - Paginator - a model defined in OpenAPI - - """ - - -Paginator.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/parent_stream_config.py b/airbyte-connector-builder-server/connector_builder/generated/models/parent_stream_config.py deleted file mode 100644 index 6daf56b137e44..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/parent_stream_config.py +++ /dev/null @@ -1,31 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.request_option import RequestOption - - -class ParentStreamConfig(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ParentStreamConfig - a model defined in OpenAPI - - stream: The stream of this ParentStreamConfig. - parent_key: The parent_key of this ParentStreamConfig. - stream_slice_field: The stream_slice_field of this ParentStreamConfig. - request_option: The request_option of this ParentStreamConfig [Optional]. - """ - - stream: object = Field(alias="stream") - parent_key: str = Field(alias="parent_key") - stream_slice_field: str = Field(alias="stream_slice_field") - request_option: Optional[RequestOption] = Field(alias="request_option", default=None) - -ParentStreamConfig.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/parsed_add_field_definition.py b/airbyte-connector-builder-server/connector_builder/generated/models/parsed_add_field_definition.py deleted file mode 100644 index 3a03c061ef3a7..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/parsed_add_field_definition.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.interpolated_string import InterpolatedString - - -class ParsedAddFieldDefinition(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ParsedAddFieldDefinition - a model defined in OpenAPI - - path: The path of this ParsedAddFieldDefinition. - value: The value of this ParsedAddFieldDefinition. - """ - - path: List[str] = Field(alias="path") - value: InterpolatedString = Field(alias="value") - -ParsedAddFieldDefinition.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/record_filter.py b/airbyte-connector-builder-server/connector_builder/generated/models/record_filter.py deleted file mode 100644 index abe54df6b6b79..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/record_filter.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class RecordFilter(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - RecordFilter - a model defined in OpenAPI - - config: The config of this RecordFilter. - condition: The condition of this RecordFilter [Optional]. - """ - - config: Dict[str, Any] = Field(alias="config") - condition: Optional[str] = Field(alias="condition", default=None) - -RecordFilter.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/record_selector.py b/airbyte-connector-builder-server/connector_builder/generated/models/record_selector.py deleted file mode 100644 index b0f46f9971ecb..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/record_selector.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.dpath_extractor import DpathExtractor -from connector_builder.generated.models.record_filter import RecordFilter -from connector_builder.generated.models.record_selector_all_of import RecordSelectorAllOf - - -class RecordSelector(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - RecordSelector - a model defined in OpenAPI - - extractor: The extractor of this RecordSelector. - record_filter: The record_filter of this RecordSelector [Optional]. - """ - - extractor: DpathExtractor = Field(alias="extractor") - record_filter: Optional[RecordFilter] = Field(alias="record_filter", default=None) - -RecordSelector.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/record_selector_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/record_selector_all_of.py deleted file mode 100644 index 0a719cc36eb74..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/record_selector_all_of.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.dpath_extractor import DpathExtractor -from connector_builder.generated.models.record_filter import RecordFilter - - -class RecordSelectorAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - RecordSelectorAllOf - a model defined in OpenAPI - - extractor: The extractor of this RecordSelectorAllOf. - record_filter: The record_filter of this RecordSelectorAllOf [Optional]. - """ - - extractor: DpathExtractor = Field(alias="extractor") - record_filter: Optional[RecordFilter] = Field(alias="record_filter", default=None) - -RecordSelectorAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/remove_fields.py b/airbyte-connector-builder-server/connector_builder/generated/models/remove_fields.py deleted file mode 100644 index ebdbca73373c3..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/remove_fields.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.remove_fields_all_of import RemoveFieldsAllOf - - -class RemoveFields(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - RemoveFields - a model defined in OpenAPI - - field_pointers: The field_pointers of this RemoveFields. - """ - - field_pointers: List[List[str]] = Field(alias="field_pointers") - -RemoveFields.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/remove_fields_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/remove_fields_all_of.py deleted file mode 100644 index a410da99f47f4..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/remove_fields_all_of.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class RemoveFieldsAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - RemoveFieldsAllOf - a model defined in OpenAPI - - field_pointers: The field_pointers of this RemoveFieldsAllOf. - """ - - field_pointers: List[List[str]] = Field(alias="field_pointers") - -RemoveFieldsAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/request_option.py b/airbyte-connector-builder-server/connector_builder/generated/models/request_option.py deleted file mode 100644 index b733d4daf3728..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/request_option.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class RequestOption(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - RequestOption - a model defined in OpenAPI - - inject_into: The inject_into of this RequestOption. - field_name: The field_name of this RequestOption [Optional]. - """ - - inject_into: str = Field(alias="inject_into") - field_name: Optional[str] = Field(alias="field_name", default=None) - -RequestOption.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/requester.py b/airbyte-connector-builder-server/connector_builder/generated/models/requester.py deleted file mode 100644 index ef05b9ae1b703..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/requester.py +++ /dev/null @@ -1,22 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class Requester(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - Requester - a model defined in OpenAPI - - """ - - -Requester.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest.py b/airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest.py deleted file mode 100644 index 81bcc339a5373..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class ResolveManifest(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ResolveManifest - a model defined in OpenAPI - - manifest: The manifest of this ResolveManifest. - """ - - manifest: Dict[str, Any] - -ResolveManifest.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest_request_body.py b/airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest_request_body.py deleted file mode 100644 index 91aded8ec5239..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/resolve_manifest_request_body.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class ResolveManifestRequestBody(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - ResolveManifestRequestBody - a model defined in OpenAPI - - manifest: The manifest of this ResolveManifestRequestBody. - """ - - manifest: Dict[str, Any] - -ResolveManifestRequestBody.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever.py b/airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever.py deleted file mode 100644 index f6f5567029ba2..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever.py +++ /dev/null @@ -1,47 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_cartesian_product_stream_slicer_datetime_stream_slicer_list_stream_slicer_single_slice_substream_slicer import AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer -from connector_builder.generated.models.any_of_default_paginator_no_pagination import AnyOfDefaultPaginatorNoPagination -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_ofarrayarraystring import AnyOfarrayarraystring -from connector_builder.generated.models.http_requester import HttpRequester -from connector_builder.generated.models.record_selector import RecordSelector -from connector_builder.generated.models.simple_retriever_all_of import SimpleRetrieverAllOf - - -class SimpleRetriever(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - SimpleRetriever - a model defined in OpenAPI - - requester: The requester of this SimpleRetriever. - record_selector: The record_selector of this SimpleRetriever. - config: The config of this SimpleRetriever. - name: The name of this SimpleRetriever [Optional]. - name: The name of this SimpleRetriever [Optional]. - primary_key: The primary_key of this SimpleRetriever [Optional]. - primary_key: The primary_key of this SimpleRetriever [Optional]. - paginator: The paginator of this SimpleRetriever [Optional]. - stream_slicer: The stream_slicer of this SimpleRetriever [Optional]. - """ - - requester: HttpRequester = Field(alias="requester") - record_selector: RecordSelector = Field(alias="record_selector") - config: Dict[str, Any] = Field(alias="config") - name: Optional[str] = Field(alias="name", default=None) - name: Optional[AnyOfInterpolatedStringstring] = Field(alias="_name", default=None) - primary_key: Optional[AnyOfarrayarraystring] = Field(alias="primary_key", default=None) - primary_key: Optional[str] = Field(alias="_primary_key", default=None) - paginator: Optional[AnyOfDefaultPaginatorNoPagination] = Field(alias="paginator", default=None) - stream_slicer: Optional[AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer] = Field(alias="stream_slicer", default=None) - -SimpleRetriever.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever_all_of.py deleted file mode 100644 index 4f11b427796c0..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/simple_retriever_all_of.py +++ /dev/null @@ -1,46 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_cartesian_product_stream_slicer_datetime_stream_slicer_list_stream_slicer_single_slice_substream_slicer import AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer -from connector_builder.generated.models.any_of_default_paginator_no_pagination import AnyOfDefaultPaginatorNoPagination -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.any_ofarrayarraystring import AnyOfarrayarraystring -from connector_builder.generated.models.http_requester import HttpRequester -from connector_builder.generated.models.record_selector import RecordSelector - - -class SimpleRetrieverAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - SimpleRetrieverAllOf - a model defined in OpenAPI - - requester: The requester of this SimpleRetrieverAllOf. - record_selector: The record_selector of this SimpleRetrieverAllOf. - config: The config of this SimpleRetrieverAllOf. - name: The name of this SimpleRetrieverAllOf [Optional]. - name: The name of this SimpleRetrieverAllOf [Optional]. - primary_key: The primary_key of this SimpleRetrieverAllOf [Optional]. - primary_key: The primary_key of this SimpleRetrieverAllOf [Optional]. - paginator: The paginator of this SimpleRetrieverAllOf [Optional]. - stream_slicer: The stream_slicer of this SimpleRetrieverAllOf [Optional]. - """ - - requester: HttpRequester = Field(alias="requester") - record_selector: RecordSelector = Field(alias="record_selector") - config: Dict[str, Any] = Field(alias="config") - name: Optional[str] = Field(alias="name", default=None) - name: Optional[AnyOfInterpolatedStringstring] = Field(alias="_name", default=None) - primary_key: Optional[AnyOfarrayarraystring] = Field(alias="primary_key", default=None) - primary_key: Optional[str] = Field(alias="_primary_key", default=None) - paginator: Optional[AnyOfDefaultPaginatorNoPagination] = Field(alias="paginator", default=None) - stream_slicer: Optional[AnyOfCartesianProductStreamSlicerDatetimeStreamSlicerListStreamSlicerSingleSliceSubstreamSlicer] = Field(alias="stream_slicer", default=None) - -SimpleRetrieverAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/single_slice.py b/airbyte-connector-builder-server/connector_builder/generated/models/single_slice.py deleted file mode 100644 index 35048024b976e..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/single_slice.py +++ /dev/null @@ -1,23 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.stream_slicer import StreamSlicer - - -class SingleSlice(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - SingleSlice - a model defined in OpenAPI - - """ - - -SingleSlice.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read.py b/airbyte-connector-builder-server/connector_builder/generated/models/stream_read.py deleted file mode 100644 index 775b148fa3a70..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read.py +++ /dev/null @@ -1,31 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 -from connector_builder.generated.models.stream_read_slices import StreamReadSlices - - -class StreamRead(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamRead - a model defined in OpenAPI - - logs: The logs of this StreamRead. - slices: The slices of this StreamRead. - test_read_limit_reached: The test_read_limit_reached of this StreamRead. - inferred_schema: The inferred_schema of this StreamRead [Optional]. - """ - - logs: List[object] - slices: List[StreamReadSlices] - test_read_limit_reached: bool - inferred_schema: Optional[Dict[str, Any]] = None - -StreamRead.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_pages.py b/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_pages.py deleted file mode 100644 index e79feb8fc3822..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_pages.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 -from connector_builder.generated.models.http_request import HttpRequest -from connector_builder.generated.models.http_response import HttpResponse - - -class StreamReadPages(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamReadPages - a model defined in OpenAPI - - records: The records of this StreamReadPages. - request: The request of this StreamReadPages [Optional]. - response: The response of this StreamReadPages [Optional]. - """ - - records: List[object] - request: Optional[HttpRequest] = None - response: Optional[HttpResponse] = None - -StreamReadPages.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_request_body.py b/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_request_body.py deleted file mode 100644 index 78bddf225b007..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_request_body.py +++ /dev/null @@ -1,42 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class StreamReadRequestBody(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamReadRequestBody - a model defined in OpenAPI - - manifest: The manifest of this StreamReadRequestBody. - stream: The stream of this StreamReadRequestBody. - config: The config of this StreamReadRequestBody. - state: The state of this StreamReadRequestBody [Optional]. - record_limit: The record_limit of this StreamReadRequestBody [Optional]. - """ - - manifest: Dict[str, Any] - stream: str - config: Dict[str, Any] - state: Optional[Dict[str, Any]] = None - record_limit: Optional[int] = None - - @validator("record_limit") - def record_limit_max(cls, value): - assert value <= 1000 - return value - - @validator("record_limit") - def record_limit_min(cls, value): - assert value >= 1 - return value - -StreamReadRequestBody.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slice_descriptor.py b/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slice_descriptor.py deleted file mode 100644 index d8cbe98f031a4..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slice_descriptor.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class StreamReadSliceDescriptor(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamReadSliceDescriptor - a model defined in OpenAPI - - start_datetime: The start_datetime of this StreamReadSliceDescriptor [Optional]. - list_item: The list_item of this StreamReadSliceDescriptor [Optional]. - """ - - start_datetime: Optional[datetime] = None - list_item: Optional[str] = None - -StreamReadSliceDescriptor.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slices.py b/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slices.py deleted file mode 100644 index 1cfddd2a9efbd..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/stream_read_slices.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 -from connector_builder.generated.models.stream_read_pages import StreamReadPages -from connector_builder.generated.models.stream_read_slice_descriptor import StreamReadSliceDescriptor - - -class StreamReadSlices(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamReadSlices - a model defined in OpenAPI - - pages: The pages of this StreamReadSlices. - slice_descriptor: The slice_descriptor of this StreamReadSlices [Optional]. - state: The state of this StreamReadSlices [Optional]. - """ - - pages: List[StreamReadPages] - slice_descriptor: Optional[StreamReadSliceDescriptor] = None - state: Optional[Dict[str, Any]] = None - -StreamReadSlices.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/stream_slicer.py b/airbyte-connector-builder-server/connector_builder/generated/models/stream_slicer.py deleted file mode 100644 index 56c37db2c82d4..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/stream_slicer.py +++ /dev/null @@ -1,22 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 - - -class StreamSlicer(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamSlicer - a model defined in OpenAPI - - """ - - -StreamSlicer.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read.py b/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read.py deleted file mode 100644 index 746b0daccb44d..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 -from connector_builder.generated.models.streams_list_read_streams import StreamsListReadStreams - - -class StreamsListRead(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamsListRead - a model defined in OpenAPI - - streams: The streams of this StreamsListRead. - """ - - streams: List[StreamsListReadStreams] - -StreamsListRead.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read_streams.py b/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read_streams.py deleted file mode 100644 index 643de2043e073..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_read_streams.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class StreamsListReadStreams(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamsListReadStreams - a model defined in OpenAPI - - name: The name of this StreamsListReadStreams. - url: The url of this StreamsListReadStreams. - """ - - name: str - url: str - -StreamsListReadStreams.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_request_body.py b/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_request_body.py deleted file mode 100644 index 1cee99805f05c..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/streams_list_request_body.py +++ /dev/null @@ -1,26 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, validator # noqa: F401 - - -class StreamsListRequestBody(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - StreamsListRequestBody - a model defined in OpenAPI - - manifest: The manifest of this StreamsListRequestBody. - config: The config of this StreamsListRequestBody. - """ - - manifest: Dict[str, Any] - config: Dict[str, Any] - -StreamsListRequestBody.update_forward_refs() diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer.py b/airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer.py deleted file mode 100644 index a5850b6fcb136..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.parent_stream_config import ParentStreamConfig -from connector_builder.generated.models.stream_slicer import StreamSlicer -from connector_builder.generated.models.substream_slicer_all_of import SubstreamSlicerAllOf - - -class SubstreamSlicer(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - SubstreamSlicer - a model defined in OpenAPI - - parent_stream_configs: The parent_stream_configs of this SubstreamSlicer. - """ - - parent_stream_configs: List[ParentStreamConfig] = Field(alias="parent_stream_configs") - -SubstreamSlicer.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer_all_of.py deleted file mode 100644 index dab0552fa671a..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/substream_slicer_all_of.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.parent_stream_config import ParentStreamConfig - - -class SubstreamSlicerAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - SubstreamSlicerAllOf - a model defined in OpenAPI - - parent_stream_configs: The parent_stream_configs of this SubstreamSlicerAllOf. - """ - - parent_stream_configs: List[ParentStreamConfig] = Field(alias="parent_stream_configs") - -SubstreamSlicerAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy.py b/airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy.py deleted file mode 100644 index cfaf856674c59..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.wait_time_from_header_backoff_strategy_all_of import WaitTimeFromHeaderBackoffStrategyAllOf - - -class WaitTimeFromHeaderBackoffStrategy(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - WaitTimeFromHeaderBackoffStrategy - a model defined in OpenAPI - - header: The header of this WaitTimeFromHeaderBackoffStrategy. - config: The config of this WaitTimeFromHeaderBackoffStrategy. - regex: The regex of this WaitTimeFromHeaderBackoffStrategy [Optional]. - """ - - header: AnyOfInterpolatedStringstring = Field(alias="header") - config: Dict[str, Any] = Field(alias="config") - regex: Optional[str] = Field(alias="regex", default=None) - -WaitTimeFromHeaderBackoffStrategy.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy_all_of.py deleted file mode 100644 index 7b2104be26362..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/wait_time_from_header_backoff_strategy_all_of.py +++ /dev/null @@ -1,29 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class WaitTimeFromHeaderBackoffStrategyAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - WaitTimeFromHeaderBackoffStrategyAllOf - a model defined in OpenAPI - - header: The header of this WaitTimeFromHeaderBackoffStrategyAllOf. - config: The config of this WaitTimeFromHeaderBackoffStrategyAllOf. - regex: The regex of this WaitTimeFromHeaderBackoffStrategyAllOf [Optional]. - """ - - header: AnyOfInterpolatedStringstring = Field(alias="header") - config: Dict[str, Any] = Field(alias="config") - regex: Optional[str] = Field(alias="regex", default=None) - -WaitTimeFromHeaderBackoffStrategyAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy.py b/airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy.py deleted file mode 100644 index 2bda5657d2379..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy.py +++ /dev/null @@ -1,33 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringnumberstring import AnyOfInterpolatedStringnumberstring -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring -from connector_builder.generated.models.wait_until_time_from_header_backoff_strategy_all_of import WaitUntilTimeFromHeaderBackoffStrategyAllOf - - -class WaitUntilTimeFromHeaderBackoffStrategy(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - WaitUntilTimeFromHeaderBackoffStrategy - a model defined in OpenAPI - - header: The header of this WaitUntilTimeFromHeaderBackoffStrategy. - config: The config of this WaitUntilTimeFromHeaderBackoffStrategy. - min_wait: The min_wait of this WaitUntilTimeFromHeaderBackoffStrategy [Optional]. - regex: The regex of this WaitUntilTimeFromHeaderBackoffStrategy [Optional]. - """ - - header: AnyOfInterpolatedStringstring = Field(alias="header") - config: Dict[str, Any] = Field(alias="config") - min_wait: Optional[AnyOfInterpolatedStringnumberstring] = Field(alias="min_wait", default=None) - regex: Optional[AnyOfInterpolatedStringstring] = Field(alias="regex", default=None) - -WaitUntilTimeFromHeaderBackoffStrategy.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy_all_of.py b/airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy_all_of.py deleted file mode 100644 index 31e6f09652487..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/generated/models/wait_until_time_from_header_backoff_strategy_all_of.py +++ /dev/null @@ -1,32 +0,0 @@ -# coding: utf-8 - -from __future__ import annotations -from datetime import date, datetime # noqa: F401 - -import re # noqa: F401 -from typing import Any, Dict, List, Optional # noqa: F401 - -from pydantic import AnyUrl, BaseModel, EmailStr, Field, validator # noqa: F401 -from connector_builder.generated.models.any_of_interpolated_stringnumberstring import AnyOfInterpolatedStringnumberstring -from connector_builder.generated.models.any_of_interpolated_stringstring import AnyOfInterpolatedStringstring - - -class WaitUntilTimeFromHeaderBackoffStrategyAllOf(BaseModel): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - - Do not edit the class manually. - - WaitUntilTimeFromHeaderBackoffStrategyAllOf - a model defined in OpenAPI - - header: The header of this WaitUntilTimeFromHeaderBackoffStrategyAllOf. - config: The config of this WaitUntilTimeFromHeaderBackoffStrategyAllOf. - min_wait: The min_wait of this WaitUntilTimeFromHeaderBackoffStrategyAllOf [Optional]. - regex: The regex of this WaitUntilTimeFromHeaderBackoffStrategyAllOf [Optional]. - """ - - header: AnyOfInterpolatedStringstring = Field(alias="header") - config: Dict[str, Any] = Field(alias="config") - min_wait: Optional[AnyOfInterpolatedStringnumberstring] = Field(alias="min_wait", default=None) - regex: Optional[AnyOfInterpolatedStringstring] = Field(alias="regex", default=None) - -WaitUntilTimeFromHeaderBackoffStrategyAllOf.update_forward_refs() \ No newline at end of file diff --git a/airbyte-connector-builder-server/connector_builder/impl/adapter.py b/airbyte-connector-builder-server/connector_builder/impl/adapter.py deleted file mode 100644 index c2a2e739a6069..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/impl/adapter.py +++ /dev/null @@ -1,42 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from abc import ABC, abstractmethod -from typing import Any, Dict, Iterator, List - -from airbyte_cdk.models import AirbyteMessage -from airbyte_cdk.sources.streams.http import HttpStream - - -class CdkAdapter(ABC): - """ - Abstract base class for the connector builder's CDK adapter. - """ - - @abstractmethod - def get_http_streams(self, config: Dict[str, Any]) -> List[HttpStream]: - """ - Gets a list of HTTP streams. - - :param config: The user-provided configuration as specified by the source's spec. - :return: A list of `HttpStream`s. - """ - - @abstractmethod - def read_stream(self, stream: str, config: Dict[str, Any]) -> Iterator[AirbyteMessage]: - """ - Reads data from the specified stream. - - :param stream: stream - :param config: The user-provided configuration as specified by the source's spec. - :return: An iterator over `AirbyteMessage` objects. - """ - - -class CdkAdapterFactory(ABC): - - @abstractmethod - def create(self, manifest: Dict[str, Any]) -> CdkAdapter: - """Return an implementation of CdkAdapter""" - pass diff --git a/airbyte-connector-builder-server/connector_builder/impl/default_api.py b/airbyte-connector-builder-server/connector_builder/impl/default_api.py deleted file mode 100644 index d3b7ea5a8bdf6..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/impl/default_api.py +++ /dev/null @@ -1,308 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import json -import logging -import traceback -from json import JSONDecodeError -from typing import Any, Dict, Iterable, Iterator, Optional, Union -from urllib.parse import parse_qs, urljoin, urlparse - -from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage, Type -from airbyte_cdk.sources.declarative.manifest_declarative_source import ManifestDeclarativeSource -from airbyte_cdk.utils.schema_inferrer import SchemaInferrer -from connector_builder.generated.apis.default_api_interface import DefaultApi -from connector_builder.generated.models.http_request import HttpRequest -from connector_builder.generated.models.http_response import HttpResponse -from connector_builder.generated.models.resolve_manifest import ResolveManifest -from connector_builder.generated.models.resolve_manifest_request_body import ResolveManifestRequestBody -from connector_builder.generated.models.stream_read import StreamRead -from connector_builder.generated.models.stream_read_pages import StreamReadPages -from connector_builder.generated.models.stream_read_request_body import StreamReadRequestBody -from connector_builder.generated.models.stream_read_slices import StreamReadSlices -from connector_builder.generated.models.streams_list_read import StreamsListRead -from connector_builder.generated.models.streams_list_read_streams import StreamsListReadStreams -from connector_builder.generated.models.streams_list_request_body import StreamsListRequestBody -from connector_builder.impl.adapter import CdkAdapter, CdkAdapterFactory -from fastapi import Body, HTTPException -from jsonschema import ValidationError - - -class DefaultApiImpl(DefaultApi): - - logger = logging.getLogger("airbyte.connector-builder") - - def __init__(self, adapter_factory: CdkAdapterFactory, max_pages_per_slice, max_slices, max_record_limit: int = 1000): - self.adapter_factory = adapter_factory - self._max_pages_per_slice = max_pages_per_slice - self._max_slices = max_slices - self.max_record_limit = max_record_limit - - super().__init__() - - async def get_manifest_template(self) -> str: - return """version: "0.1.0" -definitions: - selector: - extractor: - field_pointer: [] - requester: - url_base: "https://example.com" - http_method: "GET" - authenticator: - type: BearerAuthenticator - api_token: "{{ config['api_key'] }}" - retriever: - record_selector: - $ref: "*ref(definitions.selector)" - paginator: - type: NoPagination - requester: - $ref: "*ref(definitions.requester)" - base_stream: - retriever: - $ref: "*ref(definitions.retriever)" - customers_stream: - $ref: "*ref(definitions.base_stream)" - $options: - name: "customers" - primary_key: "id" - path: "/example" - -streams: - - "*ref(definitions.customers_stream)" - -check: - stream_names: - - "customers" - -spec: - documentation_url: https://docsurl.com - connection_specification: - title: Source Name Spec # 'TODO: Replace this with the name of your source.' - type: object - required: - - api_key - additionalProperties: true - properties: - # 'TODO: This schema defines the configuration required for the source. This usually involves metadata such as database and/or authentication information.': - api_key: - type: string - description: API Key -""" - - async def list_streams(self, streams_list_request_body: StreamsListRequestBody = Body(None, description="")) -> StreamsListRead: - """ - Takes in a low code manifest and a config to resolve the list of streams that are available for testing - :param streams_list_request_body: Input parameters to retrieve the list of available streams - :return: Stream objects made up of a stream name and the HTTP URL it will send requests to - """ - adapter = self._create_low_code_adapter(manifest=streams_list_request_body.manifest) - - stream_list_read = [] - try: - for http_stream in adapter.get_http_streams(streams_list_request_body.config): - stream_list_read.append( - StreamsListReadStreams( - name=http_stream.name, - url=urljoin(http_stream.url_base, http_stream.path()), - ) - ) - except Exception as error: - self.logger.error( - f"Could not list streams with with error: {error.args[0]} - {DefaultApiImpl._get_stacktrace_as_string(error)}" - ) - raise HTTPException(status_code=400, detail=f"Could not list streams with with error: {error.args[0]}") - return StreamsListRead(streams=stream_list_read) - - async def read_stream(self, stream_read_request_body: StreamReadRequestBody = Body(None, description="")) -> StreamRead: - """ - Using the provided manifest and config, invokes a sync for the specified stream and returns groups of Airbyte messages - that are produced during the read operation - :param stream_read_request_body: Input parameters to trigger the read operation for a stream - :param limit: The maximum number of records requested by the client (must be within the range [1, self.max_record_limit]) - :return: Airbyte record messages produced by the sync grouped by slice and page - """ - adapter = self._create_low_code_adapter(manifest=stream_read_request_body.manifest) - schema_inferrer = SchemaInferrer() - - if stream_read_request_body.record_limit is None: - record_limit = self.max_record_limit - else: - record_limit = min(stream_read_request_body.record_limit, self.max_record_limit) - - slices = [] - log_messages = [] - try: - for message_group in self._get_message_groups( - adapter.read_stream(stream_read_request_body.stream, stream_read_request_body.config), - schema_inferrer, - record_limit, - ): - if isinstance(message_group, AirbyteLogMessage): - log_messages.append({"message": message_group.message}) - else: - slices.append(message_group) - except Exception as error: - # TODO: We're temporarily using FastAPI's default exception model. Ideally we should use exceptions defined in the OpenAPI spec - self.logger.error(f"Could not perform read with with error: {error.args[0]} - {self._get_stacktrace_as_string(error)}") - raise HTTPException( - status_code=400, - detail=f"Could not perform read with with error: {error.args[0]}", - ) - - return StreamRead( - logs=log_messages, - slices=slices, - test_read_limit_reached=self._has_reached_limit(slices), - inferred_schema=schema_inferrer.get_stream_schema(stream_read_request_body.stream) - ) - - def _has_reached_limit(self, slices): - if len(slices) >= self._max_slices: - return True - - for slice in slices: - if len(slice.pages) >= self._max_pages_per_slice: - return True - return False - - async def resolve_manifest( - self, resolve_manifest_request_body: ResolveManifestRequestBody = Body(None, description="") - ) -> ResolveManifest: - """ - Using the provided manifest, resolves $refs and $options and returns the resulting manifest to the client. - :param manifest_resolve_request_body: Input manifest whose $refs and $options will be resolved - :return: Airbyte record messages produced by the sync grouped by slice and page - """ - try: - return ResolveManifest( - manifest=ManifestDeclarativeSource( - resolve_manifest_request_body.manifest, construct_using_pydantic_models=True - ).resolved_manifest - ) - except Exception as error: - self.logger.error(f"Could not resolve manifest with error: {error.args[0]} - {self._get_stacktrace_as_string(error)}") - raise HTTPException( - status_code=400, - detail=f"Could not resolve manifest with error: {error.args[0]}", - ) - - def _get_message_groups( - self, messages: Iterator[AirbyteMessage], schema_inferrer: SchemaInferrer, limit: int - ) -> Iterable[Union[StreamReadPages, AirbyteLogMessage]]: - """ - Message groups are partitioned according to when request log messages are received. Subsequent response log messages - and record messages belong to the prior request log message and when we encounter another request, append the latest - message group, until records have been read. - - Messages received from the CDK read operation will always arrive in the following order: - {type: LOG, log: {message: "request: ..."}} - {type: LOG, log: {message: "response: ..."}} - ... 0 or more record messages - {type: RECORD, record: {data: ...}} - {type: RECORD, record: {data: ...}} - Repeats for each request/response made - - Note: The exception is that normal log messages can be received at any time which are not incorporated into grouping - """ - records_count = 0 - at_least_one_page_in_group = False - current_page_records = [] - current_slice_pages = [] - current_page_request: Optional[HttpRequest] = None - current_page_response: Optional[HttpResponse] = None - - while records_count < limit and (message := next(messages, None)): - if self._need_to_close_page(at_least_one_page_in_group, message): - self._close_page(current_page_request, current_page_response, current_slice_pages, current_page_records) - current_page_request = None - current_page_response = None - - if at_least_one_page_in_group and message.type == Type.LOG and message.log.message.startswith("slice:"): - yield StreamReadSlices(pages=current_slice_pages) - current_slice_pages = [] - at_least_one_page_in_group = False - elif message.type == Type.LOG and message.log.message.startswith("request:"): - if not at_least_one_page_in_group: - at_least_one_page_in_group = True - current_page_request = self._create_request_from_log_message(message.log) - elif message.type == Type.LOG and message.log.message.startswith("response:"): - current_page_response = self._create_response_from_log_message(message.log) - elif message.type == Type.LOG: - yield message.log - elif message.type == Type.RECORD: - current_page_records.append(message.record.data) - records_count += 1 - schema_inferrer.accumulate(message.record) - else: - self._close_page(current_page_request, current_page_response, current_slice_pages, current_page_records) - yield StreamReadSlices(pages=current_slice_pages) - - @staticmethod - def _need_to_close_page(at_least_one_page_in_group, message): - return ( - at_least_one_page_in_group - and message.type == Type.LOG - and (message.log.message.startswith("request:") or message.log.message.startswith("slice:")) - ) - - @staticmethod - def _close_page(current_page_request, current_page_response, current_slice_pages, current_page_records): - if not current_page_request or not current_page_response: - raise ValueError("Every message grouping should have at least one request and response") - - current_slice_pages.append( - StreamReadPages(request=current_page_request, response=current_page_response, records=current_page_records) - ) - current_page_records.clear() - - def _create_request_from_log_message(self, log_message: AirbyteLogMessage) -> Optional[HttpRequest]: - # TODO: As a temporary stopgap, the CDK emits request data as a log message string. Ideally this should come in the - # form of a custom message object defined in the Airbyte protocol, but this unblocks us in the immediate while the - # protocol change is worked on. - raw_request = log_message.message.partition("request:")[2] - try: - request = json.loads(raw_request) - url = urlparse(request.get("url", "")) - full_path = f"{url.scheme}://{url.hostname}{url.path}" if url else "" - parameters = parse_qs(url.query) or None - return HttpRequest( - url=full_path, - http_method=request.get("http_method", ""), - headers=request.get("headers"), - parameters=parameters, - body=request.get("body"), - ) - except JSONDecodeError as error: - self.logger.warning(f"Failed to parse log message into request object with error: {error}") - return None - - def _create_response_from_log_message(self, log_message: AirbyteLogMessage) -> Optional[HttpResponse]: - # TODO: As a temporary stopgap, the CDK emits response data as a log message string. Ideally this should come in the - # form of a custom message object defined in the Airbyte protocol, but this unblocks us in the immediate while the - # protocol change is worked on. - raw_response = log_message.message.partition("response:")[2] - try: - response = json.loads(raw_response) - body = json.loads(response.get("body", "{}")) - return HttpResponse(status=response.get("status_code"), body=body, headers=response.get("headers")) - except JSONDecodeError as error: - self.logger.warning(f"Failed to parse log message into response object with error: {error}") - return None - - def _create_low_code_adapter(self, manifest: Dict[str, Any]) -> CdkAdapter: - try: - return self.adapter_factory.create(manifest) - except ValidationError as error: - # TODO: We're temporarily using FastAPI's default exception model. Ideally we should use exceptions defined in the OpenAPI spec - self.logger.error(f"Invalid connector manifest with error: {error.message} - {DefaultApiImpl._get_stacktrace_as_string(error)}") - raise HTTPException( - status_code=400, - detail=f"Invalid connector manifest with error: {error.message}", - ) - - @staticmethod - def _get_stacktrace_as_string(error) -> str: - return "".join(traceback.TracebackException.from_exception(error).format()) diff --git a/airbyte-connector-builder-server/connector_builder/impl/low_code_cdk_adapter.py b/airbyte-connector-builder-server/connector_builder/impl/low_code_cdk_adapter.py deleted file mode 100644 index 6542a0c194f35..0000000000000 --- a/airbyte-connector-builder-server/connector_builder/impl/low_code_cdk_adapter.py +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from typing import Any, Dict, Iterator, List - -from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage, ConfiguredAirbyteCatalog, Level -from airbyte_cdk.models import Type as MessageType -from airbyte_cdk.sources.declarative.declarative_stream import DeclarativeStream -from airbyte_cdk.sources.declarative.parsers.model_to_component_factory import ModelToComponentFactory -from airbyte_cdk.sources.declarative.yaml_declarative_source import ManifestDeclarativeSource -from airbyte_cdk.sources.streams.http import HttpStream -from connector_builder.impl.adapter import CdkAdapter, CdkAdapterFactory - - -class LowCodeSourceAdapter(CdkAdapter): - def __init__(self, manifest: Dict[str, Any], limit_page_fetched_per_slice, limit_slices_fetched): - # Request and response messages are only emitted for a sources that have debug turned on - self._source = ManifestDeclarativeSource( - manifest, - debug=True, - component_factory=ModelToComponentFactory(limit_page_fetched_per_slice, limit_slices_fetched) - ) - - def get_http_streams(self, config: Dict[str, Any]) -> List[HttpStream]: - http_streams = [] - for stream in self._source.streams(config=config): - if isinstance(stream, DeclarativeStream): - if isinstance(stream.retriever, HttpStream): - http_streams.append(stream.retriever) - else: - raise TypeError( - f"A declarative stream should only have a retriever of type HttpStream, but received: {stream.retriever.__class__}" - ) - else: - raise TypeError( - f"A declarative source should only contain streams of type DeclarativeStream, but received: {stream.__class__}" - ) - return http_streams - - def read_stream(self, stream: str, config: Dict[str, Any]) -> Iterator[AirbyteMessage]: - configured_catalog = ConfiguredAirbyteCatalog.parse_obj( - { - "streams": [ - { - "stream": { - "name": stream, - "json_schema": {}, - "supported_sync_modes": ["full_refresh", "incremental"], - }, - "sync_mode": "full_refresh", - "destination_sync_mode": "overwrite", - } - ] - } - ) - generator = self._source.read(logger=self._source.logger, config=config, catalog=configured_catalog) - - # the generator can raise an exception - # iterate over the generated messages. if next raise an exception, catch it and yield it as an AirbyteLogMessage - try: - yield from generator - except Exception as e: - yield AirbyteMessage(type=MessageType.LOG, log=AirbyteLogMessage(level=Level.ERROR, message=str(e))) - return - - -class LowCodeSourceAdapterFactory(CdkAdapterFactory): - - def __init__(self, max_pages_per_slice, max_slices): - self._max_pages_per_slice = max_pages_per_slice - self._max_slices = max_slices - - def create(self, manifest: Dict[str, Any]) -> CdkAdapter: - return LowCodeSourceAdapter(manifest, self._max_pages_per_slice, self._max_slices) diff --git a/airbyte-connector-builder-server/dist/connector_builder_server-0.40.21-py3.10.egg b/airbyte-connector-builder-server/dist/connector_builder_server-0.40.21-py3.10.egg deleted file mode 100644 index acb8ae91ba50e784d44325c7e47ab619536626cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3317 zcmai12{hDg7awF_l5Ay~^t~m9u~*jDzKq>4LNya(Mq`;7Os26+5eg%uNLdRxC`(yG z->5{Rh{zTqlG3ZlzPx|$d&)GY@9X)W=gfcRocp`Kd!Kvn?->Vcu5IEV5Qq;X7jqh^ zml~te&j|uGaf3iRfM3llEMRaub9)sB>wjMooChv-sfva#9Hrkc)#~Ghq*}^C4a+=< zHwE=7?rPWy#rijoDX)dfrSU-Tixpj2Ru7t3%qTBSvi0wsRIzO3Ml-rbZBE>PD3&oo z?}IIg6(4=}XC?((`o!wPva%)Z+h6G{G~|YJXO|kFhQk_M_8KSZTsL=cpSV_3;Rmj! zI`wv>HNV8Q_pa;FUqORp3M0E;9>)-m9})AwEPVr?sL4^zG|S$$J~e9h2C=AY`t7}a znnbf4pXrqqCO( zrP>X1dSKTO&(y}nr2-9w+B+sYCSjk;1Ov2WOUCKiMo5N6N7c7An6y}V};8doO}|5v^lH! zbS*M$c_*>rt7pQ-d`YOL2O>W7^Bk!Cwo~itGz_A6^s)0oS&E)~OsN%S!!{*wEKFhg zbFle!SY6GC1lL6b1s0O?$wFlIs$S0f%zF{555tjs+Wk*Q^p47zchm{Tj`JiMq&FK1 zy}$kbwsrC@nd6*$A?G@Jd;D~^?zv*Xwj<;}vVq_4!JeAW~=udVsD3xl@ho9wg_^A=Lr~^raP+mi3KhM$+x&Hgdz#C=sLe$U8P8^? zd%ZduYbh&rl=(`b>10`mdWpCz%4wotv8|+KTyiJ365rVkHo_@9uhqE#q5xme9#+C$ zSQ3`tg(YC9Xg@r`H)xaj7$@lGa7(#m_Td1lXkbgQS_fhSPU8cy|5zQOTZn2VuzI3fzwb99<*SyFM=*e#}lF)wGV65L}Jk~GTnbx+-ttxT$(C2M%IBb+XK-Tp9G}uD$Bv_CK4*OF|w7pLw zwaTX`dVoiLU~eWALnIKe7&0*s?RgsS=YDHV#cw{GyeM96TNSH3MdYP(}P#|(qDL}p_NX;>-Ehu82xx{E-Z{p2hll} zxDv#j_CeR?e4DGF)*E^oOlO+x(N7yl zEip>fCAUBeEK-gp@hEopyB6f`mr7R54=CGjk$ffJUa7B|f0e2EWxBHaBxx88lW{*7 zBU*&dk)~bcw>*fr?`q?6{@~!ZtTJunqoj)|ZcjC(HJx_0KG;|yN#?1M-yPFVnWml;Q+NmPsn<`fo<-a2#)iAp|2 zB)~M(RDpBAFyD`ldx9d@K6JNM87`}F?LN89lUG(5$04R5#1Ohprz!4=Gi>4;O+zB^ zIJ-C+!U`7_mXt(CAA}O@cqMF^r7nVC&&lyNi{5K;=9IDo5+Laj;YoTO{F#=Y&_PqE)l^;0yLe zrcb!@ki>Y?D$7&dCeiX{mijY)q;{eHb0o_)0jwJc?k6PbFYFmbeZ59G)715mlx4h36Eto_B8E;-i4DH*442CV)%G8K7f1VAxuT&C z37cJe`s#p+D`xvJ7^9^ZvKBm#ASu74@A|LGfHA+~HF4{f1OiNYd#H$Dk5#B^{8&*c zGt|OeLB8bhE$=%?;I>md6I_jDpT4ed1Y0l{9jnr&6HKIzc^s<qsbzS!Jx4CR_4_ zBYcJcuH{HUWRLe>L=-mrmv%LQc*l{4WlXu}oo8>%iAz`cqY^@u-A3?kFrguy0Loc! zx6?tBB^?E7xx<-~GUH3F?o^jZ&PPf!LT2h!<q6}+uxBK1ZV&N diff --git a/airbyte-connector-builder-server/gradle.properties b/airbyte-connector-builder-server/gradle.properties deleted file mode 100644 index 7c28b7f249211..0000000000000 --- a/airbyte-connector-builder-server/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=connector-builder-server \ No newline at end of file diff --git a/airbyte-connector-builder-server/integration_tests/test_integration_test.py b/airbyte-connector-builder-server/integration_tests/test_integration_test.py deleted file mode 100644 index f5f14bc82edf0..0000000000000 --- a/airbyte-connector-builder-server/integration_tests/test_integration_test.py +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -def test_test(): - assert True diff --git a/airbyte-connector-builder-server/openapi/README.md b/airbyte-connector-builder-server/openapi/README.md deleted file mode 100644 index e6ceb3c4e9aac..0000000000000 --- a/airbyte-connector-builder-server/openapi/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# OpenAPI templates -This directory contains custom OpenAPI templates used to generate Python code for the FastAPI. - -**But why?** - -At the time we made this service (Nov 2022), no OSS OpenAPI generators enabled spec-first development. So we made these custom templates. - -For the full context, see: https://github.com/airbytehq/airbyte/issues/17813 - -## How we're using templates -At a high level, the expected usage pattern for these templates is to generate code using the `python-fastapi` OpenAPI generator, then copy the `models` module and the `apis` into your project. This flow should work continuously i.e: as your spec evolves, it is safe to re-do this operation. - -The only change we're making to `python-fastapi` is to define an abstract class `AbstractApi` in which every method corresponds to an API endpoint. The developer is expected to extend the class and use that to instantiate the `APIRouter` provided to FastAPI. - -The existing `python-fastapi` OpenAPI generator does a pretty good job generating Pydantic models for entities declared in the OpenAPI spec, so we take those as-is. - -## Making changes to the templates -Please make sure you are at least familiar with the [User-defined Templates](https://openapi-generator.tech/docs/customization#user-defined-templates) section of the OpenAPI docs before you start iterating. - -Relevant OpenAPI docs: -- https://openapi-generator.tech/docs/customization -- https://openapi-generator.tech/docs/templating -- https://openapi-generator.tech/docs/debugging - -Happy templating! diff --git a/airbyte-connector-builder-server/openapi/generator_config.yaml b/airbyte-connector-builder-server/openapi/generator_config.yaml deleted file mode 100644 index b36cfbe63ac38..0000000000000 --- a/airbyte-connector-builder-server/openapi/generator_config.yaml +++ /dev/null @@ -1,4 +0,0 @@ -files: - api_interfaces.mustache: - templateType: API - destinationFilename: _interface.py diff --git a/airbyte-connector-builder-server/openapi/templates/api_interfaces.mustache b/airbyte-connector-builder-server/openapi/templates/api_interfaces.mustache deleted file mode 100644 index 6fd34df24e7f3..0000000000000 --- a/airbyte-connector-builder-server/openapi/templates/api_interfaces.mustache +++ /dev/null @@ -1,121 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -# This file was auto-generated from Airbyte's custom OpenAPI templates. Do not edit it manually. -# coding: utf-8 - -import inspect -from abc import ABC, abstractmethod -from typing import Callable, Dict, List # noqa: F401 - -from fastapi import ( # noqa: F401 - APIRouter, - Body, - Cookie, - Depends, - Form, - Header, - Path, - Query, - Response, - Security, - status, -) - -from {{modelPackage}}.extra_models import TokenModel # noqa: F401 - - -{{#imports}} -{{import}} -{{/imports}} - - -{{#operations}} -class {{classname}}(ABC): - """ - NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - Do not edit the class manually. - """ - - {{#operation}} - @abstractmethod - async def {{operationId}}( - self, - {{#allParams}} - {{>endpoint_argument_definition}}, - {{/allParams}} - {{#hasAuthMethods}} - {{#authMethods}} - token_{{name}}: TokenModel = Security( - get_token_{{name}}{{#isOAuth}}, scopes=[{{#scopes}}"{{scope}}"{{^-last}}, {{/-last}}{{/scopes}}]{{/isOAuth}} - ), - {{/authMethods}} - {{/hasAuthMethods}} - ) -> {{returnType}}{{^returnType}}None{{/returnType}}: - """ - {{summary}} - """ - - {{/operation}} - {{/operations}} - -def _assert_signature_is_set(method: Callable) -> None: - """ - APIRouter().add_api_route expects the input method to have a signature. It gets signatures - by running inspect.signature(method) under the hood. - - In the case that an instance method does not declare "self" as an input parameter (due to developer error - for example), then the call to inspect.signature() raises a ValueError and fails. - - Ideally, we'd automatically detect & correct this problem. To do that, we'd need to do - setattr(method, "__signature__", ) but that's not possible because instance - methods (i.e the input to this function) are object subclasses, and you can't use setattr on objects - (https://stackoverflow.com/a/12839070/3237889) - - The workaround this method implements is to raise an exception at runtime if the input method fails - when inspect.signature() is called. This is good enough because the error will be detected - immediately when the developer tries to run the server, so builds should very quickly fail and this - will practically never make it to a production scenario. - """ - try: - inspect.signature(method) - except ValueError as e: - # Based on empirical observation, the call to inspect fails with a ValueError - # with exactly one argument: "invalid method signature" - if e.args and len(e.args) == 1 and e.args[0] == "invalid method signature": - # I couldn't figure out how to setattr on a "method" object to populate the signature. For now just kick - # it back to the developer and tell them to set the "self" variable - raise Exception(f"Method {method.__name__} in class {type(method.__self__).__name__} must declare the variable 'self'. ") - else: - raise - - -{{#operations}} -def initialize_router(api: {{classname}}) -> APIRouter: - router = APIRouter() - - {{#operation}} - _assert_signature_is_set(api.{{operationId}}) - router.add_api_route( - "{{path}}", - endpoint=api.{{operationId}}, - methods=["{{#lambda.uppercase}}{{httpMethod}}{{/lambda.uppercase}}"], - responses={ - {{#responses}} - {{code}}: {{=<% %>=}}{<%#dataType%>"model": <%dataType%>, "description": "<%message%>"<%/dataType%><%^dataType%>"description": "<%message%>"<%/dataType%>}<%={{ }}=%>, - {{/responses}} - }, - tags=[{{#tags}}"{{name}}"{{^-last}},{{/-last}}{{/tags}}], - {{#summary}} - summary="{{.}}", - {{/summary}} - {{#description}} - description = "{{.}}", - {{/description}} - response_model_by_alias=True, - ) - - {{/operation}} - {{/operations}} - - return router diff --git a/airbyte-connector-builder-server/pytest.ini b/airbyte-connector-builder-server/pytest.ini deleted file mode 100644 index 58f2d9ae315e8..0000000000000 --- a/airbyte-connector-builder-server/pytest.ini +++ /dev/null @@ -1,7 +0,0 @@ -[pytest] -log_cli = 1 -log_cli_level = INFO -log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s) -log_cli_date_format=%Y-%m-%d %H:%M:%S -markers = - integration: marks tests as integration test (deselect with '-m "not integration"') \ No newline at end of file diff --git a/airbyte-connector-builder-server/run_format.sh b/airbyte-connector-builder-server/run_format.sh deleted file mode 100755 index c2ea298c112ad..0000000000000 --- a/airbyte-connector-builder-server/run_format.sh +++ /dev/null @@ -1,26 +0,0 @@ -set -e - -cd $1 - -# Fail script on failing command -set -e - -# Pasted from https://github.com/airbytehq/airbyte/blob/master/buildSrc/src/main/groovy/airbyte-python.gradle#L85-L96 -pip install 'mccabe==0.6.1' -pip install 'flake8==4.0.1' -pip install 'pyproject-flake8==0.0.1a2' -pip install 'black==22.3.0' -pip install 'mypy==0.930' -pip install 'isort==5.6.4' -pip install 'pytest==6.1.2' -pip install 'coverage[toml]==6.3.1' - -# Format and static analysis -# FIXME: isort formats python files differently from gradlew format -python -m isort --settings-file=pyproject.toml ./ -python -m isort --settings-file=pyproject.toml --diff --quiet ./ -python -m black --config pyproject.toml ./ -python -m black --config pyproject.toml ./ --diff --quiet -python -m pflake8 --config pyproject.toml ./ -python -m pflake8 --config pyproject.toml ./ --diff --quiet -python -m mypy --config pyproject.toml ./ diff --git a/airbyte-connector-builder-server/run_tests.sh b/airbyte-connector-builder-server/run_tests.sh deleted file mode 100755 index d848180139412..0000000000000 --- a/airbyte-connector-builder-server/run_tests.sh +++ /dev/null @@ -1,14 +0,0 @@ -set -e - -cd $1 - -# Fail script on failing command -set -e - -# Install dependencies -pip install -q -e . -pip install -q -e '.[tests]' - -# Run the tests -python -m coverage run -m pytest -p no:logging --disable-warnings unit_tests -c pytest.ini -python -m coverage run -m pytest -p no:logging --disable-warnings integration_tests -c pytest.ini diff --git a/airbyte-connector-builder-server/setup.py b/airbyte-connector-builder-server/setup.py deleted file mode 100644 index 906ce14627687..0000000000000 --- a/airbyte-connector-builder-server/setup.py +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import pathlib - -from setuptools import find_packages, setup - -# The directory containing this file -HERE = pathlib.Path(__file__).parent - -# The text of the README file -README = (HERE / "README.md").read_text() - -CDK_VERSION = (HERE / "CDK_VERSION").read_text() - -setup( - name="connector-builder-server", - version="0.40.32", - description="", - long_description=README, - author="Airbyte", - author_email="contact@airbyte.io", - license="MIT", - url="https://github.com/airbytehq/airbyte", - classifiers=[ - # This information is used when browsing on PyPi. - # Dev Status - "Development Status :: 3 - Alpha", - # Project Audience - "Intended Audience :: Developers", - "Topic :: Scientific/Engineering", - "Topic :: Software Development :: Libraries :: Python Modules", - "License :: OSI Approved :: MIT License", - # Python Version Support - "Programming Language :: Python :: 3.8", - ], - keywords="connect-builder", - project_urls={ - "Documentation": "https://docs.airbyte.io/", - "Source": "https://github.com/airbytehq/airbyte", - "Tracker": "https://github.com/airbytehq/airbyte/issues", - }, - packages=find_packages(exclude=("unit_tests", "integration_tests", "docs")), - package_data={}, - install_requires=[f"airbyte-cdk=={CDK_VERSION}", "fastapi", "uvicorn"], - python_requires=">=3.9.11", - extras_require={ - "tests": [ - "MyPy~=0.812", - "pytest~=6.2.5", - "pytest-cov", - "pytest-mock", - "pytest-recording", - "requests-mock", - "pre-commit", - ], - }, -) diff --git a/airbyte-connector-builder-server/src/main/openapi/openapi.yaml b/airbyte-connector-builder-server/src/main/openapi/openapi.yaml deleted file mode 100644 index 6f2147668e99f..0000000000000 --- a/airbyte-connector-builder-server/src/main/openapi/openapi.yaml +++ /dev/null @@ -1,338 +0,0 @@ -openapi: 3.0.0 -info: - description: | - Connector Builder Server API - - version: "1.0.0" - title: Connector Builder Server API - contact: - email: contact@airbyte.io - license: - name: MIT - url: "https://opensource.org/licenses/MIT" -externalDocs: - description: Find out more about Connector Builder - url: "https://docs.airbyte.com/connector-development/config-based/overview/" - -paths: - /v1/stream/read: - post: - summary: Reads a specific stream in the source. TODO in a later phase - only read a single slice of data. - operationId: readStream - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/StreamReadRequestBody" - required: true - responses: - "200": - description: Successful operation - content: - application/json: - schema: - $ref: "#/components/schemas/StreamRead" - "400": - $ref: "#/components/responses/ExceptionResponse" - "422": - $ref: "#/components/responses/InvalidInputResponse" - /v1/streams/list: - post: - summary: List all streams present in the connector manifest, along with their specific request URLs - operationId: listStreams - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/StreamsListRequestBody" - required: true - responses: - "200": - description: Successful operation - content: - application/json: - schema: - $ref: "#/components/schemas/StreamsListRead" - "400": - $ref: "#/components/responses/ExceptionResponse" - "422": - $ref: "#/components/responses/InvalidInputResponse" - /v1/manifest_template: - get: - summary: Return a connector manifest template to use as the default value for the yaml editor - operationId: getManifestTemplate - responses: - "200": - description: Successful operation - content: - application/json: - schema: - type: string - description: Connector manifest template string - /v1/manifest/resolve: - post: - summary: Given a JSON manifest, returns a JSON manifest with all of the $refs and $options resolved and flattened - operationId: resolveManifest - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/ResolveManifestRequestBody" - required: true - responses: - "200": - description: Successful operation - content: - application/json: - schema: - $ref: "#/components/schemas/ResolveManifest" - "400": - $ref: "#/components/responses/ExceptionResponse" - "422": - $ref: "#/components/responses/InvalidInputResponse" - -components: - schemas: - StreamRead: - type: object - required: - - logs - - slices - - test_read_limit_reached - properties: - logs: - type: array - description: The LOG AirbyteMessages that were emitted during the read of this slice - items: - type: object - # $ref: "#/components/schemas/AirbyteProtocol/definitions/AirbyteLogMessage" - slices: - type: array - description: The stream slices returned from the read command. If no stream slicer is configured, this should contain a single item containing all of the results. - items: - type: object - required: - - pages - properties: - pages: - type: array - description: The pages returned from the read command. If no pagination is configured, this should contain a single item containing all of the results. - items: - type: object - required: - - records - properties: - records: - type: array - description: The RECORD AirbyteMessages coming from the read operation for this page - items: - type: object - # $ref: "#/components/schemas/AirbyteProtocol/definitions/AirbyteRecordMessage" - request: - $ref: "#/components/schemas/HttpRequest" - response: - $ref: "#/components/schemas/HttpResponse" - sliceDescriptor: - type: object - description: "An object describing the current slice. This can be omitted if a stream slicer is not configured." - properties: - startDatetime: - type: string - format: date-time - listItem: - type: string - state: - type: object - description: The STATE AirbyteMessage emitted at the end of this slice. This can be omitted if a stream slicer is not configured. - # $ref: "#/components/schemas/AirbyteProtocol/definitions/AirbyteStateMessage" - test_read_limit_reached: - type: boolean - description: Whether the maximum number of request per slice or the maximum number of slices queried has been reached - inferred_schema: - type: object - description: The narrowest JSON Schema against which every AirbyteRecord in the slices can validate successfully. This is inferred from reading every record in the output slices. - StreamReadRequestBody: - type: object - required: - - manifest - - stream - - config - properties: - manifest: - type: object - description: The config-based connector manifest contents - # $ref: "#/components/schemas/ConnectorManifest" - stream: - type: string - description: Name of the stream to read - config: - type: object - description: The config blob containing the user inputs for testing - state: - type: object - description: The AirbyteStateMessage object to use as the starting state for this read - # $ref: "#/components/schemas/AirbyteProtocol/definitions/AirbyteStateMessage" - record_limit: - type: integer - minimum: 1 - maximum: 1000 - description: Number of records that will be returned to the client from the connector builder (max of 1000) - # --- Potential addition for a later phase --- - # numPages: - # type: integer - # description: Number of pages to read from the source for each slice - # default: 1 - HttpRequest: - type: object - required: - - url - - http_method - properties: - url: - type: string - description: URL that the request was sent to - parameters: - type: object - description: The request parameters that were set on the HTTP request, if any - body: - type: object - description: The body of the HTTP request, if present - headers: - type: object - description: The headers of the HTTP request, if any - http_method: - type: string - enum: ["GET", "POST", "PUT", "PATCH"] - description: The http method of the request ("GET", "POST", "PUT", or "PATCH") - HttpResponse: - type: object - required: - - status - properties: - status: - type: integer - description: The status of the response - body: - type: object - description: The body of the HTTP response, if present - headers: - type: object - description: The headers of the HTTP response, if any - # --- Commenting out for now since they do not work with our orval openapi client generator --- - # ConnectorManifest: - # $ref: ../../../../airbyte-cdk/python/airbyte_cdk/sources/declarative/config_component_schema.json - # AirbyteProtocol: - # $ref: ../../../../airbyte-protocol/protocol-models/src/main/resources/airbyte_protocol/airbyte_protocol.yaml - StreamsListRequestBody: - type: object - required: - - manifest - - config - properties: - manifest: - type: object - description: The config-based connector manifest contents - # $ref: "#/components/schemas/ConnectorManifest" - config: - type: object - description: The config blob containing the user inputs for testing - StreamsListRead: - type: object - required: - - streams - properties: - streams: - type: array - items: - type: object - description: The stream names present in the connector manifest - required: - - name - - url - properties: - name: - type: string - description: The name of the stream - url: - type: string - description: The URL to which read requests will be made for this stream - # --- Potential addition for a later phase --- - # slices: - # type: array - # description: list of slices that will be retrieved for this stream - # items: - # type: object - ResolveManifestRequestBody: - type: object - required: - - manifest - properties: - manifest: - type: object - description: The config-based connector manifest contents - ResolveManifest: - type: object - required: - - manifest - properties: - manifest: - type: object - description: The config-based connector manifest contents with $refs and $options resolved - - # The following exception structs were copied from airbyte-api/src/main/openapi/config.yaml - InvalidInputProperty: - type: object - required: - - propertyPath - properties: - propertyPath: - type: string - invalidValue: - type: string - message: - type: string - KnownExceptionInfo: - type: object - required: - - message - properties: - message: - type: string - exceptionClassName: - type: string - exceptionStack: - type: array - items: - type: string - InvalidInputExceptionInfo: - type: object - required: - - message - - validationErrors - properties: - message: - type: string - exceptionClassName: - type: string - exceptionStack: - type: array - items: - type: string - validationErrors: - type: array - items: - $ref: "#/components/schemas/InvalidInputProperty" - - responses: - InvalidInputResponse: - description: Input failed validation - content: - application/json: - schema: - $ref: "#/components/schemas/InvalidInputExceptionInfo" - ExceptionResponse: - description: Exception occurred; see message for details. - content: - application/json: - schema: - $ref: "#/components/schemas/KnownExceptionInfo" diff --git a/airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_default_api.py b/airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_default_api.py deleted file mode 100644 index 48d3df6be8af5..0000000000000 --- a/airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_default_api.py +++ /dev/null @@ -1,920 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import asyncio -import json -from typing import Iterator -from unittest.mock import MagicMock - -import pytest -from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage, AirbyteRecordMessage, Level, Type -from connector_builder.generated.models.http_request import HttpRequest -from connector_builder.generated.models.http_response import HttpResponse -from connector_builder.generated.models.resolve_manifest import ResolveManifest -from connector_builder.generated.models.resolve_manifest_request_body import ResolveManifestRequestBody -from connector_builder.generated.models.stream_read import StreamRead -from connector_builder.generated.models.stream_read_pages import StreamReadPages -from connector_builder.generated.models.stream_read_request_body import StreamReadRequestBody -from connector_builder.generated.models.streams_list_read import StreamsListRead -from connector_builder.generated.models.streams_list_read_streams import StreamsListReadStreams -from connector_builder.generated.models.streams_list_request_body import StreamsListRequestBody -from connector_builder.impl.default_api import DefaultApiImpl -from connector_builder.impl.low_code_cdk_adapter import LowCodeSourceAdapterFactory -from fastapi import HTTPException -from pydantic.error_wrappers import ValidationError - -MAX_PAGES_PER_SLICE = 4 -MAX_SLICES = 3 - -MANIFEST = { - "version": "0.1.0", - "type": "DeclarativeSource", - "definitions": { - "selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "DeclarativeSource"}, - "retriever": { - "type": "DeclarativeSource", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "hashiras_stream": { - "retriever": { - "type": "DeclarativeSource", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "hashiras", "path": "/hashiras"}, - }, - "breathing_techniques_stream": { - "retriever": { - "type": "DeclarativeSource", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "breathing-techniques", "path": "/breathing_techniques"}, - }, - }, - "streams": [ - { - "type": "DeclarativeStream", - "retriever": { - "type": "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "hashiras", "path": "/hashiras"}, - }, - { - "type": "DeclarativeStream", - "retriever": { - "type": "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "breathing-techniques", "path": "/breathing_techniques"}, - }, - ], - "check": {"stream_names": ["hashiras"], "type": "CheckStream"}, -} - -CONFIG = {"rank": "upper-six"} - - -def request_log_message(request: dict) -> AirbyteMessage: - return AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message=f"request:{json.dumps(request)}")) - - -def response_log_message(response: dict) -> AirbyteMessage: - return AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message=f"response:{json.dumps(response)}")) - - -def record_message(stream: str, data: dict) -> AirbyteMessage: - return AirbyteMessage(type=Type.RECORD, record=AirbyteRecordMessage(stream=stream, data=data, emitted_at=1234)) - - -def slice_message() -> AirbyteMessage: - return AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message='slice:{"key": "value"}')) - - -def test_list_streams(): - expected_streams = [ - StreamsListReadStreams(name="hashiras", url="https://demonslayers.com/api/v1/hashiras"), - StreamsListReadStreams(name="breathing-techniques", url="https://demonslayers.com/api/v1/breathing_techniques"), - ] - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - streams_list_request_body = StreamsListRequestBody(manifest=MANIFEST, config=CONFIG) - loop = asyncio.get_event_loop() - actual_streams = loop.run_until_complete(api.list_streams(streams_list_request_body)) - - for i, expected_stream in enumerate(expected_streams): - assert actual_streams.streams[i] == expected_stream - - -def test_list_streams_with_interpolated_urls(): - manifest = { - "version": "0.1.0", - "type": "DeclarativeSource", - "streams": [ - { - "type": "DeclarativeStream", - "retriever": { - "type": "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": { - "url_base": "https://{{ config['rank'] }}.muzan.com/api/v1/", - "http_method": "GET", - "type": "HttpRequester", - }, - }, - "$options": {"name": "demons", "path": "/demons"}, - } - ], - "check": {"stream_names": ["demons"], "type": "CheckStream"}, - } - - expected_streams = StreamsListRead(streams=[StreamsListReadStreams(name="demons", url="https://upper-six.muzan.com/api/v1/demons")]) - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - streams_list_request_body = StreamsListRequestBody(manifest=manifest, config=CONFIG) - loop = asyncio.get_event_loop() - actual_streams = loop.run_until_complete(api.list_streams(streams_list_request_body)) - - assert actual_streams == expected_streams - - -def test_list_streams_with_unresolved_interpolation(): - manifest = { - "version": "0.1.0", - "type": "DeclarativeSource", - "streams": [ - { - "type": "DeclarativeStream", - "retriever": { - "type": "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": { - "url_base": "https://{{ config['not_in_config'] }}.muzan.com/api/v1/", - "http_method": "GET", - "type": "HttpRequester", - }, - }, - "$options": {"name": "demons", "path": "/demons"}, - } - ], - "check": {"stream_names": ["demons"], "type": "CheckStream"}, - } - - # The interpolated string {{ config['not_in_config'] }} doesn't resolve to anything so it ends up blank during interpolation - expected_streams = StreamsListRead(streams=[StreamsListReadStreams(name="demons", url="https://.muzan.com/api/v1/demons")]) - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - - streams_list_request_body = StreamsListRequestBody(manifest=manifest, config=CONFIG) - loop = asyncio.get_event_loop() - actual_streams = loop.run_until_complete(api.list_streams(streams_list_request_body)) - - assert actual_streams == expected_streams - - -def test_read_stream(): - request = { - "url": "https://demonslayers.com/api/v1/hashiras?era=taisho", - "headers": {"Content-Type": "application/json"}, - "http_method": "GET", - "body": {"custom": "field"}, - } - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}', "http_method": "GET"} - expected_schema = {"$schema": "http://json-schema.org/schema#", "properties": {"name": {"type": "string"}}, "type": "object"} - expected_pages = [ - StreamReadPages( - request=HttpRequest( - url="https://demonslayers.com/api/v1/hashiras", - parameters={"era": ["taisho"]}, - headers={"Content-Type": "application/json"}, - body={"custom": "field"}, - http_method="GET", - ), - response=HttpResponse(status=200, headers={"field": "value"}, body={"name": "field"}), - records=[{"name": "Shinobu Kocho"}, {"name": "Muichiro Tokito"}], - ), - StreamReadPages( - request=HttpRequest( - url="https://demonslayers.com/api/v1/hashiras", - parameters={"era": ["taisho"]}, - headers={"Content-Type": "application/json"}, - body={"custom": "field"}, - http_method="GET", - ), - response=HttpResponse(status=200, headers={"field": "value"}, body={"name": "field"}), - records=[{"name": "Mitsuri Kanroji"}], - ), - ] - - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - record_message("hashiras", {"name": "Muichiro Tokito"}), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Mitsuri Kanroji"}), - ] - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - actual_response: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - assert actual_response.inferred_schema == expected_schema - - single_slice = actual_response.slices[0] - for i, actual_page in enumerate(single_slice.pages): - assert actual_page == expected_pages[i] - - -def test_read_stream_with_logs(): - request = { - "url": "https://demonslayers.com/api/v1/hashiras?era=taisho", - "headers": {"Content-Type": "application/json"}, - "body": {"custom": "field"}, - "http_method": "GET", - } - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}'} - expected_pages = [ - StreamReadPages( - request=HttpRequest( - url="https://demonslayers.com/api/v1/hashiras", - parameters={"era": ["taisho"]}, - headers={"Content-Type": "application/json"}, - body={"custom": "field"}, - http_method="GET", - ), - response=HttpResponse(status=200, headers={"field": "value"}, body={"name": "field"}), - records=[{"name": "Shinobu Kocho"}, {"name": "Muichiro Tokito"}], - ), - StreamReadPages( - request=HttpRequest( - url="https://demonslayers.com/api/v1/hashiras", - parameters={"era": ["taisho"]}, - headers={"Content-Type": "application/json"}, - body={"custom": "field"}, - http_method="GET", - ), - response=HttpResponse(status=200, headers={"field": "value"}, body={"name": "field"}), - records=[{"name": "Mitsuri Kanroji"}], - ), - ] - expected_logs = [ - {"message": "log message before the request"}, - {"message": "log message during the page"}, - {"message": "log message after the response"}, - ] - - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="log message before the request")), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="log message during the page")), - record_message("hashiras", {"name": "Muichiro Tokito"}), - AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="log message after the response")), - ] - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - actual_response: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - - single_slice = actual_response.slices[0] - for i, actual_page in enumerate(single_slice.pages): - assert actual_page == expected_pages[i] - - for i, actual_log in enumerate(actual_response.logs): - assert actual_log == expected_logs[i] - - -@pytest.mark.parametrize( - "request_record_limit, max_record_limit", - [ - pytest.param(1, 3, id="test_create_request_with_record_limit"), - pytest.param(3, 1, id="test_create_request_record_limit_exceeds_max"), - ], -) -def test_read_stream_record_limit(request_record_limit, max_record_limit): - request = { - "url": "https://demonslayers.com/api/v1/hashiras?era=taisho", - "headers": {"Content-Type": "application/json"}, - "body": {"custom": "field"}, - } - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}'} - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - record_message("hashiras", {"name": "Muichiro Tokito"}), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Mitsuri Kanroji"}), - response_log_message(response), - ] - ) - ) - n_records = 2 - record_limit = min(request_record_limit, max_record_limit) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES, max_record_limit=max_record_limit) - loop = asyncio.get_event_loop() - actual_response: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras", record_limit=request_record_limit)) - ) - single_slice = actual_response.slices[0] - total_records = 0 - for i, actual_page in enumerate(single_slice.pages): - total_records += len(actual_page.records) - assert total_records == min([record_limit, n_records]) - - -@pytest.mark.parametrize( - "max_record_limit", - [ - pytest.param(2, id="test_create_request_no_record_limit"), - pytest.param(1, id="test_create_request_no_record_limit_n_records_exceed_max"), - ], -) -def test_read_stream_default_record_limit(max_record_limit): - request = { - "url": "https://demonslayers.com/api/v1/hashiras?era=taisho", - "headers": {"Content-Type": "application/json"}, - "body": {"custom": "field"}, - } - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}'} - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - record_message("hashiras", {"name": "Muichiro Tokito"}), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Mitsuri Kanroji"}), - response_log_message(response), - ] - ) - ) - n_records = 2 - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES, max_record_limit=max_record_limit) - loop = asyncio.get_event_loop() - actual_response: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - single_slice = actual_response.slices[0] - total_records = 0 - for i, actual_page in enumerate(single_slice.pages): - total_records += len(actual_page.records) - assert total_records == min([max_record_limit, n_records]) - - -def test_read_stream_limit_0(): - request = { - "url": "https://demonslayers.com/api/v1/hashiras?era=taisho", - "headers": {"Content-Type": "application/json"}, - "body": {"custom": "field"}, - } - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}'} - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - record_message("hashiras", {"name": "Muichiro Tokito"}), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Mitsuri Kanroji"}), - response_log_message(response), - ] - ) - ) - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - loop = asyncio.get_event_loop() - - with pytest.raises(ValidationError): - loop.run_until_complete(api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras", record_limit=0))) - loop.run_until_complete(api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras"))) - - -def test_read_stream_no_records(): - request = { - "url": "https://demonslayers.com/api/v1/hashiras?era=taisho", - "headers": {"Content-Type": "application/json"}, - "body": {"custom": "field"}, - "http_method": "GET", - } - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}'} - expected_pages = [ - StreamReadPages( - request=HttpRequest( - url="https://demonslayers.com/api/v1/hashiras", - parameters={"era": ["taisho"]}, - headers={"Content-Type": "application/json"}, - body={"custom": "field"}, - http_method="GET", - ), - response=HttpResponse(status=200, headers={"field": "value"}, body={"name": "field"}), - records=[], - ), - StreamReadPages( - request=HttpRequest( - url="https://demonslayers.com/api/v1/hashiras", - parameters={"era": ["taisho"]}, - headers={"Content-Type": "application/json"}, - body={"custom": "field"}, - http_method="GET", - ), - response=HttpResponse(status=200, headers={"field": "value"}, body={"name": "field"}), - records=[], - ), - ] - - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - request_log_message(request), - response_log_message(response), - request_log_message(request), - response_log_message(response), - ] - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - actual_response: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - - single_slice = actual_response.slices[0] - for i, actual_page in enumerate(single_slice.pages): - assert actual_page == expected_pages[i] - - -def test_invalid_manifest(): - invalid_manifest = { - "version": "0.1.0", - "definitions": { - "selector": {"extractor": {"field_pointer": ["items"]}}, - "requester": {"http_method": "GET"}, - "retriever": { - "record_selector": {"extractor": {"field_pointer": ["items"]}}, - "paginator": {"type": "NoPagination"}, - "requester": {"http_method": "GET"}, - }, - "hashiras_stream": { - "retriever": { - "record_selector": {"extractor": {"field_pointer": ["items"]}}, - "paginator": {"type": "NoPagination"}, - "requester": {"http_method": "GET"}, - }, - "$options": {"name": "hashiras", "path": "/hashiras"}, - }, - }, - "check": {"stream_names": ["hashiras"], "class_name": "airbyte_cdk.sources.declarative.checks.check_stream.CheckStream"}, - } - - expected_status_code = 400 - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - loop = asyncio.get_event_loop() - with pytest.raises(HTTPException) as actual_exception: - loop.run_until_complete(api.read_stream(StreamReadRequestBody(manifest=invalid_manifest, config={}, stream="hashiras"))) - - assert actual_exception.value.status_code == expected_status_code - - -def test_read_stream_invalid_group_format(): - response = {"status_code": 200, "headers": {"field": "value"}, "body": '{"name": "field"}'} - - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - record_message("hashiras", {"name": "Muichiro Tokito"}), - ] - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - with pytest.raises(HTTPException) as actual_exception: - loop.run_until_complete(api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras"))) - - assert actual_exception.value.status_code == 400 - - -def test_read_stream_returns_error_if_stream_does_not_exist(): - expected_status_code = 400 - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - loop = asyncio.get_event_loop() - with pytest.raises(HTTPException) as actual_exception: - loop.run_until_complete(api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config={}, stream="not_in_manifest"))) - - assert actual_exception.value.status_code == expected_status_code - - -@pytest.mark.parametrize( - "log_message, expected_request", - [ - pytest.param( - 'request:{"url": "https://nichirin.com/v1/swords?color=orange", "http_method": "PUT", "headers": {"field": "name"}, "body":{"key": "value"}}', - HttpRequest( - url="https://nichirin.com/v1/swords", - parameters={"color": ["orange"]}, - headers={"field": "name"}, - body={"key": "value"}, - http_method="PUT", - ), - id="test_create_request_with_all_fields", - ), - pytest.param( - 'request:{"url": "https://nichirin.com/v1/swords?color=orange", "http_method": "GET", "headers": {"field": "name"}}', - HttpRequest( - url="https://nichirin.com/v1/swords", parameters={"color": ["orange"]}, headers={"field": "name"}, http_method="GET" - ), - id="test_create_request_with_no_body", - ), - pytest.param( - 'request:{"url": "https://nichirin.com/v1/swords?color=orange", "http_method": "PUT", "body":{"key": "value"}}', - HttpRequest(url="https://nichirin.com/v1/swords", parameters={"color": ["orange"]}, body={"key": "value"}, http_method="PUT"), - id="test_create_request_with_no_headers", - ), - pytest.param( - 'request:{"url": "https://nichirin.com/v1/swords", "http_method": "PUT", "headers": {"field": "name"}, "body":{"key": "value"}}', - HttpRequest(url="https://nichirin.com/v1/swords", headers={"field": "name"}, body={"key": "value"}, http_method="PUT"), - id="test_create_request_with_no_parameters", - ), - pytest.param( - 'request:{"url": "https://nichirin.com/v1/swords", "http_method": "POST", "headers": {"field": "name"}, "body":null}', - HttpRequest(url="https://nichirin.com/v1/swords", headers={"field": "name"}, body=None, http_method="POST"), - id="test_create_request_with_null_body", - ), - pytest.param("request:{invalid_json: }", None, id="test_invalid_json_still_does_not_crash"), - pytest.param("just a regular log message", None, id="test_no_request:_prefix_does_not_crash"), - ], -) -def test_create_request_from_log_message(log_message, expected_request): - airbyte_log_message = AirbyteLogMessage(level=Level.INFO, message=log_message) - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - actual_request = api._create_request_from_log_message(airbyte_log_message) - - assert actual_request == expected_request - - -@pytest.mark.parametrize( - "log_message, expected_response", - [ - pytest.param( - {"status_code": 200, "headers": {"field": "name"}, "body": '{"id":"fire", "owner": "kyojuro_rengoku"}'}, - HttpResponse(status=200, headers={"field": "name"}, body={"id": "fire", "owner": "kyojuro_rengoku"}), - id="test_create_response_with_all_fields", - ), - pytest.param( - {"status_code": 200, "headers": {"field": "name"}}, - HttpResponse(status=200, body={}, headers={"field": "name"}), - id="test_create_response_with_no_body", - ), - pytest.param( - {"status_code": 200, "body": '{"id":"fire", "owner": "kyojuro_rengoku"}'}, - HttpResponse(status=200, body={"id": "fire", "owner": "kyojuro_rengoku"}), - id="test_create_response_with_no_headers", - ), - pytest.param("request:{invalid_json: }", None, id="test_invalid_json_still_does_not_crash"), - pytest.param("just a regular log message", None, id="test_no_response:_prefix_does_not_crash"), - ], -) -def test_create_response_from_log_message(log_message, expected_response): - if isinstance(log_message, str): - response_message = log_message - else: - response_message = f"response:{json.dumps(log_message)}" - - airbyte_log_message = AirbyteLogMessage(level=Level.INFO, message=response_message) - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - actual_response = api._create_response_from_log_message(airbyte_log_message) - - assert actual_response == expected_response - - -def test_read_stream_with_many_slices(): - request = {} - response = {"status_code": 200} - - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - slice_message(), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Muichiro Tokito"}), - slice_message(), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Shinobu Kocho"}), - record_message("hashiras", {"name": "Mitsuri Kanroji"}), - request_log_message(request), - response_log_message(response), - record_message("hashiras", {"name": "Obanai Iguro"}), - request_log_message(request), - response_log_message(response), - ] - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - stream_read: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - - assert not stream_read.test_read_limit_reached - assert len(stream_read.slices) == 2 - - assert len(stream_read.slices[0].pages) == 1 - assert len(stream_read.slices[0].pages[0].records) == 1 - - assert len(stream_read.slices[1].pages) == 3 - assert len(stream_read.slices[1].pages[0].records) == 2 - assert len(stream_read.slices[1].pages[1].records) == 1 - assert len(stream_read.slices[1].pages[2].records) == 0 - - - -def test_read_stream_given_maximum_number_of_slices_then_test_read_limit_reached(): - maximum_number_of_slices = 5 - request = {} - response = {"status_code": 200} - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [ - slice_message(), - request_log_message(request), - response_log_message(response) - ] * maximum_number_of_slices - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - stream_read: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - - assert stream_read.test_read_limit_reached - - -def test_read_stream_given_maximum_number_of_pages_then_test_read_limit_reached(): - maximum_number_of_pages_per_slice = 5 - request = {} - response = {"status_code": 200} - mock_source_adapter_cls = make_mock_adapter_factory( - iter( - [slice_message()] + [request_log_message(request), response_log_message(response)] * maximum_number_of_pages_per_slice - ) - ) - - api = DefaultApiImpl(mock_source_adapter_cls, MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - stream_read: StreamRead = loop.run_until_complete( - api.read_stream(StreamReadRequestBody(manifest=MANIFEST, config=CONFIG, stream="hashiras")) - ) - - assert stream_read.test_read_limit_reached - - -def test_resolve_manifest(): - _stream_name = "stream_with_custom_requester" - _stream_primary_key = "id" - _stream_url_base = "https://api.sendgrid.com" - _stream_options = {"name": _stream_name, "primary_key": _stream_primary_key, "url_base": _stream_url_base} - - manifest = { - "version": "version", - "definitions": { - "schema_loader": {"name": "{{ options.stream_name }}", "file_path": "./source_sendgrid/schemas/{{ options.name }}.yaml"}, - "retriever": { - "paginator": { - "type": "DefaultPaginator", - "page_size": 10, - "page_size_option": {"inject_into": "request_parameter", "field_name": "page_size"}, - "page_token_option": {"inject_into": "path"}, - "pagination_strategy": {"type": "CursorPagination", "cursor_value": "{{ response._metadata.next }}"}, - }, - "requester": { - "path": "/v3/marketing/lists", - "authenticator": {"type": "BearerAuthenticator", "api_token": "{{ config.apikey }}"}, - "request_parameters": {"page_size": 10}, - }, - "record_selector": {"extractor": {"field_pointer": ["result"]}}, - }, - }, - "streams": [ - { - "type": "DeclarativeStream", - "$options": _stream_options, - "schema_loader": {"$ref": "*ref(definitions.schema_loader)"}, - "retriever": "*ref(definitions.retriever)", - }, - ], - "check": {"type": "CheckStream", "stream_names": ["lists"]}, - } - - expected_resolved_manifest = { - "type": "DeclarativeSource", - "version": "version", - "definitions": { - "schema_loader": {"name": "{{ options.stream_name }}", "file_path": "./source_sendgrid/schemas/{{ options.name }}.yaml"}, - "retriever": { - "paginator": { - "type": "DefaultPaginator", - "page_size": 10, - "page_size_option": {"inject_into": "request_parameter", "field_name": "page_size"}, - "page_token_option": {"inject_into": "path"}, - "pagination_strategy": {"type": "CursorPagination", "cursor_value": "{{ response._metadata.next }}"}, - }, - "requester": { - "path": "/v3/marketing/lists", - "authenticator": {"type": "BearerAuthenticator", "api_token": "{{ config.apikey }}"}, - "request_parameters": {"page_size": 10}, - }, - "record_selector": {"extractor": {"field_pointer": ["result"]}}, - }, - }, - "streams": [ - { - "type": "DeclarativeStream", - "schema_loader": { - "type": "JsonFileSchemaLoader", - "name": "{{ options.stream_name }}", - "file_path": "./source_sendgrid/schemas/{{ options.name }}.yaml", - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "retriever": { - "type": "SimpleRetriever", - "paginator": { - "type": "DefaultPaginator", - "page_size": 10, - "page_size_option": { - "type": "RequestOption", - "inject_into": "request_parameter", - "field_name": "page_size", - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "page_token_option": { - "type": "RequestOption", - "inject_into": "path", - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "pagination_strategy": { - "type": "CursorPagination", - "cursor_value": "{{ response._metadata.next }}", - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "requester": { - "type": "HttpRequester", - "path": "/v3/marketing/lists", - "authenticator": { - "type": "BearerAuthenticator", - "api_token": "{{ config.apikey }}", - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "request_parameters": {"page_size": 10}, - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "record_selector": { - "type": "RecordSelector", - "extractor": { - "type": "DpathExtractor", - "field_pointer": ["result"], - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - "name": _stream_name, - "primary_key": _stream_primary_key, - "url_base": _stream_url_base, - "$options": _stream_options, - }, - ], - "check": {"type": "CheckStream", "stream_names": ["lists"]}, - } - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - - loop = asyncio.get_event_loop() - actual_response: ResolveManifest = loop.run_until_complete(api.resolve_manifest(ResolveManifestRequestBody(manifest=manifest))) - assert actual_response.manifest == expected_resolved_manifest - - -def test_resolve_manifest_unresolvable_references(): - expected_status_code = 400 - - invalid_manifest = { - "version": "version", - "definitions": {}, - "streams": [ - {"type": "DeclarativeStream", "retriever": "*ref(definitions.retriever)"}, - ], - "check": {"type": "CheckStream", "stream_names": ["lists"]}, - } - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - loop = asyncio.get_event_loop() - with pytest.raises(HTTPException) as actual_exception: - loop.run_until_complete(api.resolve_manifest(ResolveManifestRequestBody(manifest=invalid_manifest))) - - assert "Undefined reference *ref(definitions.retriever)" in actual_exception.value.detail - assert actual_exception.value.status_code == expected_status_code - - -def test_resolve_manifest_invalid(): - expected_status_code = 400 - invalid_manifest = {"version": "version"} - - api = DefaultApiImpl(LowCodeSourceAdapterFactory(MAX_PAGES_PER_SLICE, MAX_SLICES), MAX_PAGES_PER_SLICE, MAX_SLICES) - loop = asyncio.get_event_loop() - with pytest.raises(HTTPException) as actual_exception: - loop.run_until_complete(api.resolve_manifest(ResolveManifestRequestBody(manifest=invalid_manifest))) - - assert "Could not resolve manifest with error" in actual_exception.value.detail - assert actual_exception.value.status_code == expected_status_code - - -def make_mock_adapter_factory(return_value: Iterator) -> MagicMock: - mock_source_adapter_factory = MagicMock() - mock_source_adapter = MagicMock() - mock_source_adapter.read_stream.return_value = return_value - mock_source_adapter_factory.create.return_value = mock_source_adapter - return mock_source_adapter_factory diff --git a/airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_low_code_cdk_adapter.py b/airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_low_code_cdk_adapter.py deleted file mode 100644 index c1230b418063c..0000000000000 --- a/airbyte-connector-builder-server/unit_tests/connector_builder/impl/test_low_code_cdk_adapter.py +++ /dev/null @@ -1,354 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from abc import ABC -from typing import Any, List, Mapping, Optional, Union -from unittest.mock import MagicMock - -import pytest -import requests -from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage, AirbyteRecordMessage, Level, Type -from airbyte_cdk.sources.declarative.declarative_stream import DeclarativeStream -from airbyte_cdk.sources.declarative.requesters.paginators import PaginatorTestReadDecorator -from airbyte_cdk.sources.declarative.retrievers.simple_retriever import SimpleRetrieverTestReadDecorator -from airbyte_cdk.sources.declarative.parsers.custom_exceptions import UndefinedReferenceException -from airbyte_cdk.sources.streams.http import HttpStream - -from connector_builder.impl.low_code_cdk_adapter import LowCodeSourceAdapter - - -class MockConcreteStream(HttpStream, ABC): - """ - Test class used to verify errors are correctly thrown when the adapter receives unexpected outputs - """ - - def primary_key(self) -> Optional[Union[str, List[str], List[List[str]]]]: - return None - - def url_base(self) -> str: - return "" - - def path( - self, - *, - stream_state: Mapping[str, Any] = None, - stream_slice: Mapping[str, Any] = None, - next_page_token: Mapping[str, Any] = None, - ) -> str: - return "" - - def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: - return None - - def parse_response( - self, - response: requests.Response, - *, - stream_state: Mapping[str, Any], - stream_slice: Mapping[str, Any] = None, - next_page_token: Mapping[str, Any] = None, - ) -> Optional[str]: - return None - - -MANIFEST = { - "version": "0.1.0", - "type" : "DeclarativeSource", - "definitions": { - "selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type" : "DeclarativeSource" }, - "retriever": { - "type" : "DeclarativeSource", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "hashiras_stream": { - "retriever": { - "type" : "DeclarativeSource", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "hashiras", "path": "/hashiras"}, - }, - "breathing_techniques_stream": { - "retriever": { - "type" : "DeclarativeSource", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "breathing-techniques", "path": "/breathing_techniques"}, - }, - }, - "streams": [ - { - "type" : "DeclarativeStream", - "retriever": { - "type" : "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "hashiras", "path": "/hashiras"}, - }, - { - "type" : "DeclarativeStream", - "retriever": { - "type" : "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": {"type": "NoPagination"}, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "breathing-techniques", "path": "/breathing_techniques"}, - }, - ], - "check": {"stream_names": ["hashiras"], "type": "CheckStream"}, -} - -MANIFEST_WITH_REFERENCES = { - "version": "0.1.0", - "type" : "DeclarativeSource", - "definitions": { - "selector": { - "type": "RecordSelector", - "extractor": { - "type": "DpathExtractor", - "field_pointer": [] - } - }, - "requester": { - "type": "HttpRequester", - "url_base": "https://demonslayers.com/api/v1/", - "http_method": "GET", - "authenticator": { - "type": "BearerAuthenticator", - "api_token": "{{ config['api_key'] }}" - } - }, - "retriever": { - "type": "SimpleRetriever", - "record_selector": { - "$ref": "*ref(definitions.selector)" - }, - "paginator": { - "type": "NoPagination" - }, - "requester": { - "$ref": "*ref(definitions.requester)" - } - }, - "base_stream": { - "type": "DeclarativeStream", - "retriever": { - "$ref": "*ref(definitions.retriever)" - } - }, - "ranks_stream": { - "$ref": "*ref(definitions.base_stream)", - "$options": { - "name": "ranks", - "primary_key": "id", - "path": "/ranks" - } - } - }, - "streams": ["*ref(definitions.ranks_stream)"], - "check": { - "type": "CheckStream", - "stream_names": ["ranks"] - }, - "spec": { - "type": "Spec", - "documentation_url": "https://docsurl.com", - "connection_specification": { - "title": "Source Name Spec", - "type": "object", - "required": ["api_key"], - "additionalProperties": True, - "properties": { - "api_key": { - "type": "string", - "description": "API Key" - } - } - } - } -} - -MANIFEST_WITH_PAGINATOR = { - "version": "0.1.0", - "type" : "DeclarativeSource", - "definitions": { - }, - "streams": [ - { - "type" : "DeclarativeStream", - "retriever": { - "type" : "SimpleRetriever", - "record_selector": {"extractor": {"field_pointer": ["items"], "type": "DpathExtractor"}, "type": "RecordSelector"}, - "paginator": { - "type": "DefaultPaginator", - "pagination_strategy": { - "type": "OffsetIncrement", - "page_size": 10 - }, - "url_base": "https://demonslayers.com/api/v1/" - }, - "requester": {"url_base": "https://demonslayers.com/api/v1/", "http_method": "GET", "type": "HttpRequester"}, - }, - "$options": {"name": "hashiras", "path": "/hashiras"}, - }, - ], - "check": {"stream_names": ["hashiras"], "type": "CheckStream"}, -} - -def test_get_http_streams(): - expected_urls = {"https://demonslayers.com/api/v1/breathing_techniques", "https://demonslayers.com/api/v1/hashiras"} - - adapter = LowCodeSourceAdapter(MANIFEST, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - actual_streams = adapter.get_http_streams(config={}) - actual_urls = {http_stream.url_base + http_stream.path() for http_stream in actual_streams} - - assert len(actual_streams) == len(expected_urls) - assert actual_urls == expected_urls - - -MAXIMUM_NUMBER_OF_PAGES_PER_SLICE = 5 -MAXIMUM_NUMBER_OF_SLICES = 5 - -def test_get_http_manifest_with_references(): - expected_urls = {"https://demonslayers.com/api/v1/ranks"} - - adapter = LowCodeSourceAdapter(MANIFEST_WITH_REFERENCES, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - actual_streams = adapter.get_http_streams(config={}) - actual_urls = {http_stream.url_base + http_stream.path() for http_stream in actual_streams} - - assert len(actual_streams) == len(expected_urls) - assert actual_urls == expected_urls - - -def test_get_http_streams_non_declarative_streams(): - non_declarative_stream = MockConcreteStream() - - mock_source = MagicMock() - mock_source.streams.return_value = [non_declarative_stream] - - adapter = LowCodeSourceAdapter(MANIFEST, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - adapter._source = mock_source - with pytest.raises(TypeError): - adapter.get_http_streams(config={}) - - -def test_get_http_streams_non_http_stream(): - declarative_stream_non_http_retriever = DeclarativeStream(name="hashiras", primary_key="id", retriever=MagicMock(), config={}, - options={}) - - mock_source = MagicMock() - mock_source.streams.return_value = [declarative_stream_non_http_retriever] - - adapter = LowCodeSourceAdapter(MANIFEST, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - adapter._source = mock_source - with pytest.raises(TypeError): - adapter.get_http_streams(config={}) - - -def test_read_streams(): - expected_messages = iter([ - AirbyteMessage( - type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="request:{'url': 'https://demonslayers.com/v1/hashiras'}") - ), - AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="response:{'status': 200}")), - AirbyteMessage( - type=Type.RECORD, - record=AirbyteRecordMessage(data={"name": "Tengen Uzui", "breathing_technique": "sound"}, emitted_at=1234, stream="hashiras"), - ), - AirbyteMessage( - type=Type.RECORD, - record=AirbyteRecordMessage( - data={"name": "Kyojuro Rengoku", "breathing_technique": "fire"}, emitted_at=1234, stream="hashiras" - ), - ), - AirbyteMessage( - type=Type.RECORD, - record=AirbyteRecordMessage(data={"name": "Giyu Tomioka", "breathing_technique": "water"}, emitted_at=1234, stream="hashiras"), - ), - ]) - mock_source = MagicMock() - mock_source.read.return_value = expected_messages - - adapter = LowCodeSourceAdapter(MANIFEST, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - adapter._source = mock_source - actual_messages = list(adapter.read_stream("hashiras", {})) - - for i, expected_message in enumerate(expected_messages): - assert actual_messages[i] == expected_message - - -def test_read_streams_with_error(): - expected_messages = [ - AirbyteMessage( - type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="request:{'url': 'https://demonslayers.com/v1/hashiras'}") - ), - AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.INFO, message="response:{'status': 401}")), - AirbyteMessage(type=Type.LOG, log=AirbyteLogMessage(level=Level.ERROR, message="error_message")), - ] - mock_source = MagicMock() - - def return_value(*args, **kwargs): - yield expected_messages[0] - yield expected_messages[1] - raise Exception("error_message") - - mock_source.read.side_effect = return_value - - adapter = LowCodeSourceAdapter(MANIFEST, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - adapter._source = mock_source - actual_messages = list(adapter.read_stream("hashiras", {})) - - for i, expected_message in enumerate(expected_messages): - assert actual_messages[i] == expected_message - - -def test_read_streams_invalid_reference(): - invalid_reference_manifest = { - "version": "0.1.0", - "type" : "DeclarativeSource", - "definitions": { - "selector": { - "type": "RecordSelector", - "extractor": { - "type": "DpathExtractor", - "field_pointer": [] - } - }, - "ranks_stream": { - "$ref": "*ref(definitions.base_stream)", - "$options": { - "name": "ranks", - "primary_key": "id", - "path": "/ranks" - } - } - }, - "streams": ["*ref(definitions.ranks_stream)"], - "check": { - "type": "CheckStream", - "stream_names": ["ranks"] - } - } - - with pytest.raises(UndefinedReferenceException): - LowCodeSourceAdapter(invalid_reference_manifest, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - - -def test_stream_use_read_test_retriever_and_paginator(): - adapter = LowCodeSourceAdapter(MANIFEST_WITH_PAGINATOR, MAXIMUM_NUMBER_OF_PAGES_PER_SLICE, MAXIMUM_NUMBER_OF_SLICES) - streams = adapter.get_http_streams(config={}) - - assert streams - for stream in streams: - assert isinstance(stream, SimpleRetrieverTestReadDecorator) - assert isinstance(stream.paginator, PaginatorTestReadDecorator) diff --git a/airbyte-connector-builder-server/unit_tests/test_unit_test.py b/airbyte-connector-builder-server/unit_tests/test_unit_test.py deleted file mode 100644 index f5f14bc82edf0..0000000000000 --- a/airbyte-connector-builder-server/unit_tests/test_unit_test.py +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - - -def test_test(): - assert True diff --git a/airbyte-container-orchestrator/Dockerfile b/airbyte-container-orchestrator/Dockerfile deleted file mode 100644 index 02baa3b4a03ad..0000000000000 --- a/airbyte-container-orchestrator/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -ARG JDK_IMAGE=airbyte/airbyte-base-java-image:1.0 -FROM ${JDK_IMAGE} AS orchestrator - -ARG DOCKER_BUILD_ARCH=amd64 - -RUN amazon-linux-extras install -y docker -RUN yum install -y jq tar && yum clean all - -RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${DOCKER_BUILD_ARCH}/kubectl" \ - && chmod +x kubectl && mv kubectl /usr/local/bin/ - -# Don't change this manually. Bump version expects to make moves based on this string -ARG VERSION=0.40.32 - -ENV APPLICATION airbyte-container-orchestrator -ENV VERSION=${VERSION} -ENV AIRBYTE_ENTRYPOINT "/app/${APPLICATION}-${VERSION}/bin/${APPLICATION}" - -WORKDIR /app - -# Grab well-known types file -COPY WellKnownTypes.json /app - -# Move orchestrator app -ADD bin/${APPLICATION}-${VERSION}.tar /app - -# wait for upstream dependencies to become available before starting server -ENTRYPOINT ["/bin/bash", "-c", "/app/${APPLICATION}-${VERSION}/bin/${APPLICATION}"] diff --git a/airbyte-container-orchestrator/build.gradle b/airbyte-container-orchestrator/build.gradle deleted file mode 100644 index 75da6541cc1d6..0000000000000 --- a/airbyte-container-orchestrator/build.gradle +++ /dev/null @@ -1,95 +0,0 @@ -import groovy.json.JsonBuilder -import groovy.yaml.YamlSlurper - -plugins { - id 'application' -} - -configurations { - airbyteProtocol -} - -dependencies { - annotationProcessor platform(libs.micronaut.bom) - annotationProcessor libs.bundles.micronaut.annotation.processor - - implementation platform(libs.micronaut.bom) - implementation libs.bundles.micronaut - - // Ensure that the versions defined in deps.toml are used - // instead of versions from transitive dependencies - implementation(libs.s3) { - // Force to avoid updated version brought in transitively from Micronaut 3.8+ - // that is incompatible with our current Helm setup - force = true - } - implementation(libs.aws.java.sdk.s3) { - // Force to avoid updated version brought in transitively from Micronaut 3.8+ - // that is incompatible wit hour current Helm setup - force = true - } - - implementation 'io.fabric8:kubernetes-client:5.12.2' - implementation libs.bundles.datadog - - implementation project(':airbyte-api') - implementation project(':airbyte-config:config-models') - implementation project(':airbyte-commons-protocol') - implementation project(':airbyte-commons-temporal') - implementation project(':airbyte-commons-worker') - implementation project(':airbyte-config:init') - implementation project(':airbyte-featureflag') - implementation project(':airbyte-json-validation') - implementation libs.airbyte.protocol - implementation project(':airbyte-metrics:metrics-lib') - implementation project(':airbyte-worker-models') - - testAnnotationProcessor platform(libs.micronaut.bom) - testAnnotationProcessor libs.bundles.micronaut.test.annotation.processor - - testImplementation libs.bundles.micronaut.test - testImplementation 'org.mockito:mockito-inline:2.13.0' - testImplementation libs.postgresql - testImplementation libs.platform.testcontainers - testImplementation libs.platform.testcontainers.postgresql - - airbyteProtocol(libs.airbyte.protocol) { - transitive = false - } -} - -application { - applicationName = "airbyte-container-orchestrator" - mainClass = "io.airbyte.container_orchestrator.Application" - applicationDefaultJvmArgs = ['-XX:+ExitOnOutOfMemoryError', '-XX:MaxRAMPercentage=75.0'] -} - -// Duplicated from :airbyte-worker, eventually, this should be handled in :airbyte-protocol -task generateWellKnownTypes() { - doLast { - def wellKnownTypesYamlPath = 'airbyte_protocol/well_known_types.yaml' - configurations.airbyteProtocol.getFiles().each { - def zip = new java.util.zip.ZipFile(it) - def entry = zip.getEntry(wellKnownTypesYamlPath) - - def wellKnownTypesYaml = zip.getInputStream(entry).text - def parsedYaml = new YamlSlurper().parseText(wellKnownTypesYaml) - def wellKnownTypesJson = new JsonBuilder(parsedYaml).toPrettyString() - def targetFile = project.file("build/docker/WellKnownTypes.json") - targetFile.getParentFile().mkdirs() - targetFile.text = wellKnownTypesJson - } - } -} - -tasks.named("buildDockerImage") { - dependsOn copyGeneratedTar - dependsOn generateWellKnownTypes -} - -// Ideally, we would have buildDockerImage depend on generateWellKnownTypes -// but some of our actions use copyGeneratedTar as the "set up the docker build context" task -// so we'll just add it here. -tasks.named("copyGeneratedTar") { - dependsOn generateWellKnownTypes -} diff --git a/airbyte-container-orchestrator/gradle.properties b/airbyte-container-orchestrator/gradle.properties deleted file mode 100644 index b98ac03de2eaa..0000000000000 --- a/airbyte-container-orchestrator/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=container-orchestrator diff --git a/airbyte-container-orchestrator/readme.md b/airbyte-container-orchestrator/readme.md deleted file mode 100644 index 05f8a46120b4c..0000000000000 --- a/airbyte-container-orchestrator/readme.md +++ /dev/null @@ -1,6 +0,0 @@ -# airbyte-container-orchestrator - -This module contains logic to handle launching connector containers. It is called from the temporal workflows in `airbyte-workers`. It is called from the worker and spins up in a separate pod so that sync workflows can be isolated from each other. - -## Entrypoint -* `ContainerOrchestratorApp.java` diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/Application.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/Application.java deleted file mode 100644 index af03f4902035e..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/Application.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.commons.logging.LoggingHelper; -import io.airbyte.commons.logging.MdcScope; -import io.airbyte.container_orchestrator.orchestrator.JobOrchestrator; -import io.airbyte.workers.process.AsyncKubePodStatus; -import io.micronaut.runtime.Micronaut; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.lang.invoke.MethodHandles; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Entrypoint for the application responsible for launching containers and handling all message - * passing for replication, normalization, and dbt. Also, the current version relies on a heartbeat - * from a Temporal worker. This will also be removed in the future so this can run fully async. - *

- * This application retrieves most of its configuration from copied files from the calling Temporal - * worker. - *

- * This app uses default logging which is directly captured by the calling Temporal worker. In the - * future this will need to independently interact with cloud storage. - */ -@SuppressWarnings({"PMD.AvoidCatchingThrowable", "PMD.DoNotTerminateVM", "PMD.AvoidFieldNameMatchingTypeName"}) -@Singleton -public class Application { - - public static void main(final String[] args) { - // To mimic previous behavior, assume an exit code of 1 unless Application.run returns otherwise. - var exitCode = 1; - try (final var ctx = Micronaut.run(Application.class, args)) { - exitCode = ctx.getBean(Application.class).run(); - } catch (final Throwable t) { - log.error("could not run {}", t.getMessage(), t); - } finally { - // this mimics the pre-micronaut code, unsure if there is a better way in micronaut to ensure a - // non-zero exit code - System.exit(exitCode); - } - } - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private final String application; - private final JobOrchestrator jobOrchestrator; - private final AsyncStateManager asyncStateManager; - - public Application(@Named("application") final String application, - final JobOrchestrator jobOrchestrator, - final AsyncStateManager asyncStateManager) { - this.application = application; - this.jobOrchestrator = jobOrchestrator; - this.asyncStateManager = asyncStateManager; - } - - /** - * Configures logging/mdc scope, and creates all objects necessary to handle state updates. - *

- * Handles state updates (including writing failures) and running the job orchestrator. As much of - * the initialization as possible should go in here, so it's logged properly and the state storage - * is updated appropriately. - */ - @VisibleForTesting - int run() { - // set mdc scope for the remaining execution - try (final var mdcScope = new MdcScope.Builder() - .setLogPrefix(application) - .setPrefixColor(LoggingHelper.Color.CYAN_BACKGROUND) - .build()) { - - asyncStateManager.write(AsyncKubePodStatus.INITIALIZING); - asyncStateManager.write(AsyncKubePodStatus.RUNNING); - asyncStateManager.write(AsyncKubePodStatus.SUCCEEDED, jobOrchestrator.runJob().orElse("")); - } catch (final Throwable t) { - log.error("Killing orchestrator because of an Exception", t); - asyncStateManager.write(AsyncKubePodStatus.FAILED); - return 1; - } - - return 0; - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/AsyncStateManager.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/AsyncStateManager.java deleted file mode 100644 index ea65906810ed3..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/AsyncStateManager.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import com.google.common.annotations.VisibleForTesting; -import io.airbyte.workers.process.AsyncKubePodStatus; -import io.airbyte.workers.process.KubePodInfo; -import io.airbyte.workers.storage.DocumentStoreClient; -import jakarta.inject.Singleton; -import java.lang.invoke.MethodHandles; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The state manager writes the "truth" for states of the async pod process. If the store isn't - * updated by the underlying pod, it will appear as failed. - *

- * It doesn't have a single value for a state. Instead, in a location on cloud storage or disk, it - * writes every state it's encountered. - */ -@Singleton -public class AsyncStateManager { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private static final List STATUS_CHECK_ORDER = List.of( - // terminal states first - AsyncKubePodStatus.FAILED, - AsyncKubePodStatus.SUCCEEDED, - // then check in progress state - AsyncKubePodStatus.RUNNING, - // then check for initialization state - AsyncKubePodStatus.INITIALIZING); - - private final DocumentStoreClient documentStoreClient; - private final KubePodInfo kubePodInfo; - - public AsyncStateManager(final DocumentStoreClient documentStoreClient, final KubePodInfo kubePodInfo) { - this.documentStoreClient = documentStoreClient; - this.kubePodInfo = kubePodInfo; - } - - /** - * Writes an empty file to a location designated by the input status. - */ - public void write(final AsyncKubePodStatus status, final String value) { - final var key = getDocumentStoreKey(status); - log.info("Writing async status {} for {}...", status, kubePodInfo); - documentStoreClient.write(key, value); - } - - /** - * Writes a file containing a string value to a location designated by the input status. - */ - public void write(final AsyncKubePodStatus status) { - write(status, ""); - } - - /** - * Interprets the state given all written state messages for the pod. - *

- * Checks terminal states first, then running, then initialized. Defaults to not started. - *

- * The order matters here! - */ - public AsyncKubePodStatus getStatus() { - return STATUS_CHECK_ORDER.stream() - .filter(this::statusFileExists) - .findFirst() - .orElse(AsyncKubePodStatus.NOT_STARTED); - } - - /** - * @return the output stored in the success file. This can be an empty string. - * @throws IllegalArgumentException if no success file exists - */ - public String getOutput() throws IllegalArgumentException { - final var key = getDocumentStoreKey(AsyncKubePodStatus.SUCCEEDED); - final var output = documentStoreClient.read(key); - - return output.orElseThrow(() -> new IllegalArgumentException("Expected to retrieve output from a successfully completed pod!")); - - } - - /** - * IMPORTANT: Changing the storage location will orphan already existing kube pods when the new - * version is deployed! - */ - @VisibleForTesting - String getDocumentStoreKey(final AsyncKubePodStatus status) { - return kubePodInfo.namespace() + "/" + kubePodInfo.name() + "/" + status.name(); - } - - private boolean statusFileExists(final AsyncKubePodStatus status) { - final var key = getDocumentStoreKey(status); - return documentStoreClient.read(key).isPresent(); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/EventListeners.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/EventListeners.java deleted file mode 100644 index ed2bebc887545..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/EventListeners.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import io.airbyte.commons.temporal.TemporalUtils; -import io.airbyte.commons.temporal.sync.OrchestratorConstants; -import io.airbyte.config.EnvConfigs; -import io.airbyte.config.helpers.LogClientSingleton; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.micronaut.runtime.event.annotation.EventListener; -import io.micronaut.runtime.server.event.ServerStartupEvent; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.lang.invoke.MethodHandles; -import java.util.Map; -import java.util.function.BiFunction; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.LoggerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class EventListeners { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final Map envVars; - private final EnvConfigs configs; - private final JobRunConfig jobRunConfig; - private final BiFunction propertySetter; - - @Inject - EventListeners(@Named("envVars") final Map envVars, final EnvConfigs configs, final JobRunConfig jobRunConfig) { - this(envVars, configs, jobRunConfig, (name, value) -> { - System.setProperty(name, value); - return null; - }); - } - - /** - * Exists only for overriding the default property setter for testing - */ - EventListeners(@Named("envVars") final Map envVars, - final EnvConfigs configs, - final JobRunConfig jobRunConfig, - final BiFunction propertySetter) { - this.envVars = envVars; - this.configs = configs; - this.jobRunConfig = jobRunConfig; - this.propertySetter = propertySetter; - } - - /** - * Configures the environment variables for this app. - *

- * Should this be replaced with env-vars set on the container itself? - * - * @param unused required so Micronaut knows when to run this event-listener, but not used - */ - @EventListener - void setEnvVars(final ServerStartupEvent unused) { - log.info("settings env vars"); - - OrchestratorConstants.ENV_VARS_TO_TRANSFER.stream() - .filter(envVars::containsKey) - .forEach(envVar -> propertySetter.apply(envVar, envVars.get(envVar))); - } - - /** - * Configures the logging for this app. - * - * @param unused required so Micronaut knows when to run this event-listener, but not used - */ - @EventListener - void setLogging(final ServerStartupEvent unused) { - log.info("started logging"); - - // make sure the new configuration is picked up - final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - ctx.reconfigure(); - - LogClientSingleton.getInstance().setJobMdc( - configs.getWorkerEnvironment(), - configs.getLogConfigs(), - TemporalUtils.getJobRoot(configs.getWorkspaceRoot(), jobRunConfig.getJobId(), jobRunConfig.getAttemptId())); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/HeartbeatController.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/HeartbeatController.java deleted file mode 100644 index 8cdce37ed4cc5..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/HeartbeatController.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Get; -import io.micronaut.http.annotation.Produces; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import java.util.Map; - -/** - * Creates a controller that returns a 200 JSON response on any path requested. - *

- * This is intended to stay up as long as the Kube worker exists so pods spun up can check if the - * spawning Kube worker still exists. - */ -// @TODO remove this annotation -@Secured(SecurityRule.IS_ANONYMOUS) -@Controller -public class HeartbeatController { - - private static final Map response = Map.of("up", true); - - @Get - @Produces(MediaType.APPLICATION_JSON) - public Map get() { - return response; - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ConfigFactory.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ConfigFactory.java deleted file mode 100644 index 17042cb9d760f..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ConfigFactory.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.config; - -import com.fasterxml.jackson.core.type.TypeReference; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.temporal.sync.OrchestratorConstants; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.workers.process.AsyncOrchestratorPodProcess; -import io.airbyte.workers.process.KubePodInfo; -import io.airbyte.workers.process.KubePodProcess; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import jakarta.annotation.Nullable; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; - -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -@Factory -public class ConfigFactory { - - /** - * Returns the config directory which contains all the configuration files. - * - * @param configDir optional directory, defaults to KubePodProcess.CONFIG_DIR if not defined. - * @return Configuration directory. - */ - @Singleton - @Named("configDir") - String configDir(@Value("${airbyte.config-dir}") @Nullable final String configDir) { - if (configDir == null) { - return KubePodProcess.CONFIG_DIR; - } - return configDir; - } - - /** - * Returns the contents of the OrchestratorConstants.INIT_FILE_APPLICATION file. - * - * @param configDir Which directory contains the OrchestratorConstants.INIT_FILE_APPLICATION file. - * @return Contents of OrchestratorConstants.INIT_FILE_APPLICATION - * @throws IOException - */ - @Singleton - @Named("application") - String application(@Named("configDir") final String configDir) throws IOException { - return Files.readString(Path.of(configDir, OrchestratorConstants.INIT_FILE_APPLICATION)); - } - - /** - * Returns the contents of the OrchestratorConstants.INIT_FILE_ENV_MAP file. - * - * @param configDir Which directory contains the OrchestratorConstants.INIT_FILE_ENV_MAP file. - * @return Contents of OrchestratorConstants.INIT_FILE_ENV_MAP - */ - @Singleton - @Named("envVars") - Map envVars(@Named("configDir") final String configDir) { - return Jsons.deserialize( - Path.of(configDir, OrchestratorConstants.INIT_FILE_ENV_MAP).toFile(), new TypeReference<>() {}); - } - - /** - * Returns the contents of the OrchestratorConstants.INIT_FILE_JOB_RUN_CONFIG file. - * - * @param configDir Which directory contains the OrchestratorConstants.INIT_FILE_JOB_RUN_CONFIG - * file. - * @return Contents of OrchestratorConstants.INIT_FILE_JOB_RUN_CONFIG - */ - @Singleton - JobRunConfig jobRunConfig(@Named("configDir") final String configDir) { - return Jsons.deserialize(Path.of(configDir, OrchestratorConstants.INIT_FILE_JOB_RUN_CONFIG).toFile(), JobRunConfig.class); - } - - /** - * Returns the contents of the OrchestratorConstants.KUBE_POD_INFO file. - * - * @param configDir Which directory contains the OrchestratorConstants.KUBE_POD_INFO file. - * @return Contents of OrchestratorConstants.KUBE_POD_INFO - */ - @Singleton - KubePodInfo kubePodInfo(@Named("configDir") final String configDir) { - return Jsons.deserialize(Path.of(configDir, AsyncOrchestratorPodProcess.KUBE_POD_INFO).toFile(), KubePodInfo.class); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactory.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactory.java deleted file mode 100644 index 74004a3e802d2..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactory.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.config; - -import io.airbyte.api.client.generated.DestinationApi; -import io.airbyte.api.client.generated.SourceApi; -import io.airbyte.commons.features.EnvVariableFeatureFlags; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.protocol.AirbyteMessageSerDeProvider; -import io.airbyte.commons.protocol.AirbyteProtocolVersionedMigratorFactory; -import io.airbyte.commons.temporal.sync.OrchestratorConstants; -import io.airbyte.config.EnvConfigs; -import io.airbyte.container_orchestrator.orchestrator.DbtJobOrchestrator; -import io.airbyte.container_orchestrator.orchestrator.JobOrchestrator; -import io.airbyte.container_orchestrator.orchestrator.NoOpOrchestrator; -import io.airbyte.container_orchestrator.orchestrator.NormalizationJobOrchestrator; -import io.airbyte.container_orchestrator.orchestrator.ReplicationJobOrchestrator; -import io.airbyte.featureflag.FeatureFlagClient; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.workers.WorkerConfigs; -import io.airbyte.workers.process.AsyncOrchestratorPodProcess; -import io.airbyte.workers.process.DockerProcessFactory; -import io.airbyte.workers.process.KubePortManagerSingleton; -import io.airbyte.workers.process.KubeProcessFactory; -import io.airbyte.workers.process.ProcessFactory; -import io.airbyte.workers.storage.DocumentStoreClient; -import io.airbyte.workers.storage.StateClients; -import io.airbyte.workers.sync.DbtLauncherWorker; -import io.airbyte.workers.sync.NormalizationLauncherWorker; -import io.airbyte.workers.sync.ReplicationLauncherWorker; -import io.fabric8.kubernetes.client.DefaultKubernetesClient; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.annotation.Value; -import io.micronaut.context.env.Environment; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.file.Path; -import java.util.Map; - -@Factory -class ContainerOrchestratorFactory { - - @Singleton - FeatureFlags featureFlags() { - return new EnvVariableFeatureFlags(); - } - - @Singleton - EnvConfigs envConfigs(@Named("envVars") final Map env) { - return new EnvConfigs(env); - } - - @Singleton - WorkerConfigs workerConfigs(final EnvConfigs envConfigs) { - return new WorkerConfigs(envConfigs); - } - - @Singleton - @Requires(notEnv = Environment.KUBERNETES) - ProcessFactory dockerProcessFactory(final WorkerConfigs workerConfigs, final EnvConfigs configs) { - return new DockerProcessFactory( - workerConfigs, - configs.getWorkspaceRoot(), // Path.of(workspaceRoot), - configs.getWorkspaceDockerMount(), // workspaceDockerMount, - configs.getLocalDockerMount(), // localDockerMount, - configs.getDockerNetwork()// dockerNetwork - ); - } - - @Singleton - @Requires(env = Environment.KUBERNETES) - ProcessFactory kubeProcessFactory( - final WorkerConfigs workerConfigs, - final EnvConfigs configs, - @Value("${micronaut.server.port}") final int serverPort) - throws UnknownHostException { - final var localIp = InetAddress.getLocalHost().getHostAddress(); - final var kubeHeartbeatUrl = localIp + ":" + serverPort; - - // this needs to have two ports for the source and two ports for the destination (all four must be - // exposed) - KubePortManagerSingleton.init(OrchestratorConstants.PORTS); - - return new KubeProcessFactory( - workerConfigs, - configs.getJobKubeNamespace(), - new DefaultKubernetesClient(), - kubeHeartbeatUrl, - false); - } - - @Singleton - JobOrchestrator jobOrchestrator( - @Named("application") final String application, - final EnvConfigs envConfigs, - final ProcessFactory processFactory, - final FeatureFlags featureFlags, - final FeatureFlagClient featureFlagClient, - final WorkerConfigs workerConfigs, - final AirbyteMessageSerDeProvider serdeProvider, - final AirbyteProtocolVersionedMigratorFactory migratorFactory, - final JobRunConfig jobRunConfig, - final SourceApi sourceApi, - final DestinationApi destinationApi) { - return switch (application) { - case ReplicationLauncherWorker.REPLICATION -> new ReplicationJobOrchestrator(envConfigs, processFactory, featureFlags, featureFlagClient, - serdeProvider, - migratorFactory, jobRunConfig, sourceApi, destinationApi); - case NormalizationLauncherWorker.NORMALIZATION -> new NormalizationJobOrchestrator(envConfigs, processFactory, jobRunConfig); - case DbtLauncherWorker.DBT -> new DbtJobOrchestrator(envConfigs, workerConfigs, processFactory, jobRunConfig); - case AsyncOrchestratorPodProcess.NO_OP -> new NoOpOrchestrator(); - default -> throw new IllegalStateException("Could not find job orchestrator for application: " + application); - }; - } - - @Singleton - DocumentStoreClient documentStoreClient(final EnvConfigs config) { - return StateClients.create(config.getStateStorageCloudConfigs(), Path.of("/state")); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/DbtJobOrchestrator.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/DbtJobOrchestrator.java deleted file mode 100644 index 7ca402da3b30b..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/DbtJobOrchestrator.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.orchestrator; - -import static io.airbyte.metrics.lib.ApmTraceConstants.JOB_ORCHESTRATOR_OPERATION_NAME; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.DESTINATION_DOCKER_IMAGE_KEY; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.JOB_ID_KEY; - -import datadog.trace.api.Trace; -import io.airbyte.commons.temporal.TemporalUtils; -import io.airbyte.config.Configs; -import io.airbyte.config.OperatorDbtInput; -import io.airbyte.metrics.lib.ApmTraceUtils; -import io.airbyte.persistence.job.models.IntegrationLauncherConfig; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.workers.WorkerConfigs; -import io.airbyte.workers.general.DbtTransformationRunner; -import io.airbyte.workers.general.DbtTransformationWorker; -import io.airbyte.workers.normalization.DefaultNormalizationRunner; -import io.airbyte.workers.process.KubePodProcess; -import io.airbyte.workers.process.ProcessFactory; -import io.airbyte.workers.sync.ReplicationLauncherWorker; -import java.lang.invoke.MethodHandles; -import java.nio.file.Path; -import java.util.Map; -import java.util.Optional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DbtJobOrchestrator implements JobOrchestrator { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final Configs configs; - private final WorkerConfigs workerConfigs; - private final ProcessFactory processFactory; - private final JobRunConfig jobRunConfig; - - public DbtJobOrchestrator(final Configs configs, - final WorkerConfigs workerConfigs, - final ProcessFactory processFactory, - final JobRunConfig jobRunConfig) { - this.configs = configs; - this.workerConfigs = workerConfigs; - this.processFactory = processFactory; - this.jobRunConfig = jobRunConfig; - } - - @Override - public String getOrchestratorName() { - return "DBT Transformation"; - } - - @Override - public Class getInputClass() { - return OperatorDbtInput.class; - } - - @Trace(operationName = JOB_ORCHESTRATOR_OPERATION_NAME) - @Override - public Optional runJob() throws Exception { - final OperatorDbtInput dbtInput = readInput(); - - final IntegrationLauncherConfig destinationLauncherConfig = JobOrchestrator.readAndDeserializeFile( - Path.of(KubePodProcess.CONFIG_DIR, - ReplicationLauncherWorker.INIT_FILE_DESTINATION_LAUNCHER_CONFIG), - IntegrationLauncherConfig.class); - - ApmTraceUtils - .addTagsToTrace(Map.of(JOB_ID_KEY, jobRunConfig.getJobId(), DESTINATION_DOCKER_IMAGE_KEY, - destinationLauncherConfig.getDockerImage())); - - log.info("Setting up dbt worker..."); - final DbtTransformationWorker worker = new DbtTransformationWorker( - jobRunConfig.getJobId(), - Math.toIntExact(jobRunConfig.getAttemptId()), - workerConfigs.getResourceRequirements(), - new DbtTransformationRunner( - processFactory, new DefaultNormalizationRunner( - processFactory, - destinationLauncherConfig.getNormalizationDockerImage(), - destinationLauncherConfig.getNormalizationIntegrationType()))); - - log.info("Running dbt worker..."); - final Path jobRoot = TemporalUtils.getJobRoot(configs.getWorkspaceRoot(), - jobRunConfig.getJobId(), jobRunConfig.getAttemptId()); - worker.run(dbtInput, jobRoot); - - return Optional.empty(); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/JobOrchestrator.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/JobOrchestrator.java deleted file mode 100644 index 27c549f60d6d3..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/JobOrchestrator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.orchestrator; - -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.temporal.sync.OrchestratorConstants; -import io.airbyte.workers.process.KubePodProcess; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Optional; - -/** - * The job orchestrator helps abstract over container launcher application differences across - * replication, normalization, and custom dbt operators. - * - * @param job input type - */ -public interface JobOrchestrator { - - // used for logging - String getOrchestratorName(); - - // used to serialize the loaded input - Class getInputClass(); - - // reads input from a file that was copied to the container launcher - default INPUT readInput() throws IOException { - return Jsons.deserialize( - Path.of(KubePodProcess.CONFIG_DIR, OrchestratorConstants.INIT_FILE_INPUT).toFile(), - getInputClass()); - } - - /** - * Contains the unique logic that belongs to each type of job. - * - * @return an optional output value to place within the output document store item. - */ - Optional runJob() throws Exception; - - static T readAndDeserializeFile(final Path path, final Class type) throws IOException { - return Jsons.deserialize(Files.readString(path), type); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NoOpOrchestrator.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NoOpOrchestrator.java deleted file mode 100644 index 3582fced895c9..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NoOpOrchestrator.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.orchestrator; - -import io.airbyte.workers.process.AsyncOrchestratorPodProcess; -import java.lang.invoke.MethodHandles; -import java.util.Optional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * For testing only. - */ -public class NoOpOrchestrator implements JobOrchestrator { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - @Override - public String getOrchestratorName() { - return AsyncOrchestratorPodProcess.NO_OP; - } - - @Override - public Class getInputClass() { - return String.class; - } - - @Override - public Optional runJob() throws Exception { - log.info("Running no-op job."); - return Optional.empty(); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NormalizationJobOrchestrator.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NormalizationJobOrchestrator.java deleted file mode 100644 index 4b9d4608f66ed..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/NormalizationJobOrchestrator.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.orchestrator; - -import static io.airbyte.metrics.lib.ApmTraceConstants.JOB_ORCHESTRATOR_OPERATION_NAME; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.DESTINATION_DOCKER_IMAGE_KEY; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.JOB_ID_KEY; - -import datadog.trace.api.Trace; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.temporal.TemporalUtils; -import io.airbyte.config.Configs; -import io.airbyte.config.NormalizationInput; -import io.airbyte.config.NormalizationSummary; -import io.airbyte.metrics.lib.ApmTraceUtils; -import io.airbyte.persistence.job.models.IntegrationLauncherConfig; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.workers.general.DefaultNormalizationWorker; -import io.airbyte.workers.normalization.DefaultNormalizationRunner; -import io.airbyte.workers.normalization.NormalizationWorker; -import io.airbyte.workers.process.KubePodProcess; -import io.airbyte.workers.process.ProcessFactory; -import io.airbyte.workers.sync.ReplicationLauncherWorker; -import java.nio.file.Path; -import java.util.Map; -import java.util.Optional; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class NormalizationJobOrchestrator implements JobOrchestrator { - - private final Configs configs; - private final ProcessFactory processFactory; - private final JobRunConfig jobRunConfig; - - public NormalizationJobOrchestrator(final Configs configs, final ProcessFactory processFactory, final JobRunConfig jobRunConfig) { - this.configs = configs; - this.processFactory = processFactory; - this.jobRunConfig = jobRunConfig; - } - - @Override - public String getOrchestratorName() { - return "Normalization"; - } - - @Override - public Class getInputClass() { - return NormalizationInput.class; - } - - @Trace(operationName = JOB_ORCHESTRATOR_OPERATION_NAME) - @Override - public Optional runJob() throws Exception { - // final JobRunConfig jobRunConfig = readJobRunConfig(); - final NormalizationInput normalizationInput = readInput(); - - final IntegrationLauncherConfig destinationLauncherConfig = JobOrchestrator.readAndDeserializeFile( - Path.of(KubePodProcess.CONFIG_DIR, - ReplicationLauncherWorker.INIT_FILE_DESTINATION_LAUNCHER_CONFIG), - IntegrationLauncherConfig.class); - - ApmTraceUtils - .addTagsToTrace(Map.of(JOB_ID_KEY, jobRunConfig.getJobId(), DESTINATION_DOCKER_IMAGE_KEY, - destinationLauncherConfig.getDockerImage())); - - log.info("Setting up normalization worker..."); - final NormalizationWorker normalizationWorker = new DefaultNormalizationWorker( - jobRunConfig.getJobId(), - Math.toIntExact(jobRunConfig.getAttemptId()), - new DefaultNormalizationRunner( - processFactory, - destinationLauncherConfig.getNormalizationDockerImage(), - destinationLauncherConfig.getNormalizationIntegrationType()), - configs.getWorkerEnvironment()); - - log.info("Running normalization worker..."); - final Path jobRoot = TemporalUtils.getJobRoot(configs.getWorkspaceRoot(), - jobRunConfig.getJobId(), jobRunConfig.getAttemptId()); - final NormalizationSummary normalizationSummary = normalizationWorker.run(normalizationInput, - jobRoot); - - return Optional.of(Jsons.serialize(normalizationSummary)); - } - -} diff --git a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/ReplicationJobOrchestrator.java b/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/ReplicationJobOrchestrator.java deleted file mode 100644 index fadbeaad52072..0000000000000 --- a/airbyte-container-orchestrator/src/main/java/io/airbyte/container_orchestrator/orchestrator/ReplicationJobOrchestrator.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.orchestrator; - -import static io.airbyte.metrics.lib.ApmTraceConstants.JOB_ORCHESTRATOR_OPERATION_NAME; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.DESTINATION_DOCKER_IMAGE_KEY; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.JOB_ID_KEY; -import static io.airbyte.metrics.lib.ApmTraceConstants.Tags.SOURCE_DOCKER_IMAGE_KEY; - -import datadog.trace.api.Trace; -import io.airbyte.api.client.generated.DestinationApi; -import io.airbyte.api.client.generated.SourceApi; -import io.airbyte.commons.features.FeatureFlagHelper; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.logging.MdcScope; -import io.airbyte.commons.protocol.AirbyteMessageSerDeProvider; -import io.airbyte.commons.protocol.AirbyteProtocolVersionedMigratorFactory; -import io.airbyte.commons.temporal.TemporalUtils; -import io.airbyte.commons.version.Version; -import io.airbyte.config.Configs; -import io.airbyte.config.ReplicationOutput; -import io.airbyte.config.StandardSyncInput; -import io.airbyte.featureflag.FeatureFlagClient; -import io.airbyte.featureflag.FieldSelectionEnabled; -import io.airbyte.featureflag.Workspace; -import io.airbyte.metrics.lib.ApmTraceUtils; -import io.airbyte.metrics.lib.MetricClientFactory; -import io.airbyte.metrics.lib.MetricEmittingApps; -import io.airbyte.persistence.job.models.IntegrationLauncherConfig; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; -import io.airbyte.workers.RecordSchemaValidator; -import io.airbyte.workers.WorkerConstants; -import io.airbyte.workers.WorkerMetricReporter; -import io.airbyte.workers.WorkerUtils; -import io.airbyte.workers.general.DefaultReplicationWorker; -import io.airbyte.workers.helper.ConnectorConfigUpdater; -import io.airbyte.workers.internal.AirbyteStreamFactory; -import io.airbyte.workers.internal.DefaultAirbyteDestination; -import io.airbyte.workers.internal.DefaultAirbyteSource; -import io.airbyte.workers.internal.DefaultAirbyteStreamFactory; -import io.airbyte.workers.internal.EmptyAirbyteSource; -import io.airbyte.workers.internal.NamespacingMapper; -import io.airbyte.workers.internal.VersionedAirbyteMessageBufferedWriterFactory; -import io.airbyte.workers.internal.VersionedAirbyteStreamFactory; -import io.airbyte.workers.internal.book_keeping.AirbyteMessageTracker; -import io.airbyte.workers.process.AirbyteIntegrationLauncher; -import io.airbyte.workers.process.KubePodProcess; -import io.airbyte.workers.process.ProcessFactory; -import io.airbyte.workers.sync.ReplicationLauncherWorker; -import java.lang.invoke.MethodHandles; -import java.nio.file.Path; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ReplicationJobOrchestrator implements JobOrchestrator { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final ProcessFactory processFactory; - private final Configs configs; - private final FeatureFlags featureFlags; - private final FeatureFlagClient featureFlagClient; - private final AirbyteMessageSerDeProvider serDeProvider; - private final AirbyteProtocolVersionedMigratorFactory migratorFactory; - private final JobRunConfig jobRunConfig; - private final SourceApi sourceApi; - private final DestinationApi destinationApi; - - public ReplicationJobOrchestrator(final Configs configs, - final ProcessFactory processFactory, - final FeatureFlags featureFlags, - final FeatureFlagClient featureFlagClient, - final AirbyteMessageSerDeProvider serDeProvider, - final AirbyteProtocolVersionedMigratorFactory migratorFactory, - final JobRunConfig jobRunConfig, - final SourceApi sourceApi, - final DestinationApi destinationApi) { - this.configs = configs; - this.processFactory = processFactory; - this.featureFlags = featureFlags; - this.featureFlagClient = featureFlagClient; - this.serDeProvider = serDeProvider; - this.migratorFactory = migratorFactory; - this.jobRunConfig = jobRunConfig; - this.sourceApi = sourceApi; - this.destinationApi = destinationApi; - } - - @Override - public String getOrchestratorName() { - return "Replication"; - } - - @Override - public Class getInputClass() { - return StandardSyncInput.class; - } - - @Trace(operationName = JOB_ORCHESTRATOR_OPERATION_NAME) - @Override - public Optional runJob() throws Exception { - final var syncInput = readInput(); - - final var sourceLauncherConfig = JobOrchestrator.readAndDeserializeFile( - Path.of(KubePodProcess.CONFIG_DIR, ReplicationLauncherWorker.INIT_FILE_SOURCE_LAUNCHER_CONFIG), - IntegrationLauncherConfig.class); - - final var destinationLauncherConfig = JobOrchestrator.readAndDeserializeFile( - Path.of(KubePodProcess.CONFIG_DIR, ReplicationLauncherWorker.INIT_FILE_DESTINATION_LAUNCHER_CONFIG), - IntegrationLauncherConfig.class); - log.info("sourceLauncherConfig is: " + sourceLauncherConfig.toString()); - - ApmTraceUtils.addTagsToTrace( - Map.of(JOB_ID_KEY, jobRunConfig.getJobId(), - DESTINATION_DOCKER_IMAGE_KEY, destinationLauncherConfig.getDockerImage(), - SOURCE_DOCKER_IMAGE_KEY, sourceLauncherConfig.getDockerImage())); - - // At this moment, if either source or destination is from custom connector image, we will put all - // jobs into isolated pool to run. - final boolean useIsolatedPool = sourceLauncherConfig.getIsCustomConnector() || destinationLauncherConfig.getIsCustomConnector(); - log.info("Setting up source launcher..."); - final var sourceLauncher = new AirbyteIntegrationLauncher( - sourceLauncherConfig.getJobId(), - Math.toIntExact(sourceLauncherConfig.getAttemptId()), - sourceLauncherConfig.getDockerImage(), - processFactory, - syncInput.getSourceResourceRequirements(), - sourceLauncherConfig.getAllowedHosts(), - useIsolatedPool, - featureFlags); - - log.info("Setting up destination launcher..."); - final var destinationLauncher = new AirbyteIntegrationLauncher( - destinationLauncherConfig.getJobId(), - Math.toIntExact(destinationLauncherConfig.getAttemptId()), - destinationLauncherConfig.getDockerImage(), - processFactory, - syncInput.getDestinationResourceRequirements(), - destinationLauncherConfig.getAllowedHosts(), - useIsolatedPool, - featureFlags); - - log.info("Setting up source..."); - // reset jobs use an empty source to induce resetting all data in destination. - final var airbyteSource = - WorkerConstants.RESET_JOB_SOURCE_DOCKER_IMAGE_STUB.equals(sourceLauncherConfig.getDockerImage()) ? new EmptyAirbyteSource( - featureFlags.useStreamCapableState()) - : new DefaultAirbyteSource(sourceLauncher, - getStreamFactory(sourceLauncherConfig.getProtocolVersion(), syncInput.getCatalog(), DefaultAirbyteSource.CONTAINER_LOG_MDC_BUILDER), - migratorFactory.getProtocolSerializer(sourceLauncherConfig.getProtocolVersion()), featureFlags); - - MetricClientFactory.initialize(MetricEmittingApps.WORKER); - final var metricClient = MetricClientFactory.getMetricClient(); - final var metricReporter = new WorkerMetricReporter(metricClient, - sourceLauncherConfig.getDockerImage()); - - log.info("Setting up replication worker..."); - final UUID workspaceId = syncInput.getWorkspaceId(); - // NOTE: we apply field selection if the feature flag client says so (recommended) or the old - // environment-variable flags say so (deprecated). - // The latter FeatureFlagHelper will be removed once the flag client is fully deployed. - final boolean fieldSelectionEnabled = workspaceId != null && - (featureFlagClient.enabled(FieldSelectionEnabled.INSTANCE, new Workspace(workspaceId)) - || FeatureFlagHelper.isFieldSelectionEnabledForWorkspace(featureFlags, workspaceId)); - final var replicationWorker = new DefaultReplicationWorker( - jobRunConfig.getJobId(), - Math.toIntExact(jobRunConfig.getAttemptId()), - airbyteSource, - new NamespacingMapper(syncInput.getNamespaceDefinition(), syncInput.getNamespaceFormat(), syncInput.getPrefix()), - new DefaultAirbyteDestination(destinationLauncher, - getStreamFactory(destinationLauncherConfig.getProtocolVersion(), syncInput.getCatalog(), - DefaultAirbyteDestination.CONTAINER_LOG_MDC_BUILDER), - new VersionedAirbyteMessageBufferedWriterFactory(serDeProvider, migratorFactory, destinationLauncherConfig.getProtocolVersion(), - Optional.of(syncInput.getCatalog())), - migratorFactory.getProtocolSerializer(destinationLauncherConfig.getProtocolVersion())), - new AirbyteMessageTracker(featureFlags), - new RecordSchemaValidator(featureFlagClient, syncInput.getWorkspaceId(), WorkerUtils.mapStreamNamesToSchemas(syncInput)), - metricReporter, - new ConnectorConfigUpdater(sourceApi, destinationApi), - fieldSelectionEnabled); - - log.info("Running replication worker..."); - final var jobRoot = TemporalUtils.getJobRoot(configs.getWorkspaceRoot(), - jobRunConfig.getJobId(), jobRunConfig.getAttemptId()); - final ReplicationOutput replicationOutput = replicationWorker.run(syncInput, jobRoot); - - log.info("Returning output..."); - return Optional.of(Jsons.serialize(replicationOutput)); - } - - private AirbyteStreamFactory getStreamFactory(final Version protocolVersion, - final ConfiguredAirbyteCatalog configuredAirbyteCatalog, - final MdcScope.Builder mdcScope) { - return protocolVersion != null - ? new VersionedAirbyteStreamFactory<>(serDeProvider, migratorFactory, protocolVersion, Optional.of(configuredAirbyteCatalog), mdcScope, - Optional.of(RuntimeException.class)) - : new DefaultAirbyteStreamFactory(mdcScope); - } - -} diff --git a/airbyte-container-orchestrator/src/main/resources/application.yml b/airbyte-container-orchestrator/src/main/resources/application.yml deleted file mode 100644 index cb3caae40b1fc..0000000000000 --- a/airbyte-container-orchestrator/src/main/resources/application.yml +++ /dev/null @@ -1,53 +0,0 @@ -micronaut: - server: - port: 9000 - -airbyte: - config-dir: /config - acceptance: - test: - enabled: ${ACCEPTANCE_TEST_ENABLED:false} - control: - plane: - auth-endpoint: ${CONTROL_PLANE_AUTH_ENDPOINT:} - data: - plane: - service-account: - credentials-path: ${DATA_PLANE_SERVICE_ACCOUNT_CREDENTIALS_PATH:} - email: ${DATA_PLANE_SERVICE_ACCOUNT_EMAIL:} - feature-flag: - client: ${FEATURE_FLAG_CLIENT:config} - path: ${FEATURE_FLAG_PATH:/flags} - api-key: ${LAUNCHDARKLY_KEY:} - internal: - api: - auth-header: - name: ${AIRBYTE_API_AUTH_HEADER_NAME:} - value: ${AIRBYTE_API_AUTH_HEADER_VALUE:} - host: ${INTERNAL_API_HOST} - -endpoints: - beans: - enabled: true - sensitive: false - env: - enabled: true - sensitive: false - health: - enabled: true - sensitive: false - info: - enabled: true - sensitive: true - loggers: - enabled: true - sensitive: true - refresh: - enabled: false - sensitive: true - routes: - enabled: true - sensitive: false - threaddump: - enabled: true - sensitive: true diff --git a/airbyte-container-orchestrator/src/main/resources/micronaut-banner.txt b/airbyte-container-orchestrator/src/main/resources/micronaut-banner.txt deleted file mode 100644 index cc4505457b9ed..0000000000000 --- a/airbyte-container-orchestrator/src/main/resources/micronaut-banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - - ___ _ __ __ - / | (_)____/ /_ __ __/ /____ - / /| | / / ___/ __ \/ / / / __/ _ \ - / ___ |/ / / / /_/ / /_/ / /_/ __/ -/_/ |_/_/_/ /_.___/\__, /\__/\___/ - /____/ - : airbyte-container-orchestrator : \ No newline at end of file diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/ApplicationTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/ApplicationTest.java deleted file mode 100644 index 552f766f8a809..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/ApplicationTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.airbyte.container_orchestrator.orchestrator.JobOrchestrator; -import io.airbyte.workers.process.AsyncKubePodStatus; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class ApplicationTest { - - private String application; - private JobOrchestrator jobOrchestrator; - private AsyncStateManager asyncStateManager; - - @BeforeEach - void setup() { - jobOrchestrator = mock(JobOrchestrator.class); - asyncStateManager = mock(AsyncStateManager.class); - } - - @Test - void testHappyPath() throws Exception { - final var output = "job-output"; - when(jobOrchestrator.runJob()).thenReturn(Optional.of(output)); - - final var app = new Application(application, jobOrchestrator, asyncStateManager); - final var code = app.run(); - - assertEquals(0, code); - verify(jobOrchestrator).runJob(); - verify(asyncStateManager).write(AsyncKubePodStatus.INITIALIZING); - verify(asyncStateManager).write(AsyncKubePodStatus.RUNNING); - verify(asyncStateManager).write(AsyncKubePodStatus.SUCCEEDED, output); - } - - @Test - void testJobFailedWritesFailedStatus() throws Exception { - when(jobOrchestrator.runJob()).thenThrow(new Exception()); - final var app = new Application(application, jobOrchestrator, asyncStateManager); - final var code = app.run(); - - assertEquals(1, code); - verify(jobOrchestrator).runJob(); - verify(asyncStateManager).write(AsyncKubePodStatus.INITIALIZING); - verify(asyncStateManager).write(AsyncKubePodStatus.RUNNING); - verify(asyncStateManager).write(AsyncKubePodStatus.FAILED); - } - -} diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/AsyncStateManagerTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/AsyncStateManagerTest.java deleted file mode 100644 index aabefcb86b6e5..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/AsyncStateManagerTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.airbyte.workers.process.AsyncKubePodStatus; -import io.airbyte.workers.process.KubeContainerInfo; -import io.airbyte.workers.process.KubePodInfo; -import io.airbyte.workers.storage.DocumentStoreClient; -import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class AsyncStateManagerTest { - - public static final String FAKE_IMAGE = "fake_image"; - private static final KubePodInfo KUBE_POD_INFO = new KubePodInfo("default", "pod1", - new KubeContainerInfo(FAKE_IMAGE, "IfNotPresent")); - private static final String OUTPUT = "some output value"; - - private DocumentStoreClient documentStore; - private AsyncStateManager stateManager; - - @BeforeEach - void setup() { - documentStore = mock(DocumentStoreClient.class); - stateManager = new AsyncStateManager(documentStore, KUBE_POD_INFO); - } - - @Test - void testEmptyWrite() { - stateManager.write(AsyncKubePodStatus.INITIALIZING); - - // test for overwrite (which should be allowed) - stateManager.write(AsyncKubePodStatus.INITIALIZING); - - final var key = stateManager.getDocumentStoreKey(AsyncKubePodStatus.INITIALIZING); - verify(documentStore, times(2)).write(key, ""); - } - - @Test - void testContentfulWrite() { - stateManager.write(AsyncKubePodStatus.SUCCEEDED, OUTPUT); - - final var key = stateManager.getDocumentStoreKey(AsyncKubePodStatus.SUCCEEDED); - verify(documentStore, times(1)).write(key, OUTPUT); - } - - @Test - void testReadingOutputWhenItExists() { - final var key = stateManager.getDocumentStoreKey(AsyncKubePodStatus.SUCCEEDED); - when(documentStore.read(key)).thenReturn(Optional.of(OUTPUT)); - assertEquals(OUTPUT, stateManager.getOutput()); - } - - @Test - void testReadingOutputWhenItDoesNotExist() { - // getting the output should throw an exception when there is no record in the document store - assertThrows(IllegalArgumentException.class, () -> { - stateManager.getOutput(); - }); - } - - @Test - void testSuccessfulStatusRetrievalLifecycle() { - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.INITIALIZING))).thenReturn(Optional.empty()); - final var beforeInitializingStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.NOT_STARTED, beforeInitializingStatus); - - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.INITIALIZING))).thenReturn(Optional.of("")); - final var initializingStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.INITIALIZING, initializingStatus); - - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.RUNNING))).thenReturn(Optional.of("")); - final var runningStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.RUNNING, runningStatus); - - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.SUCCEEDED))).thenReturn( - Optional.of("output")); - final var succeededStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.SUCCEEDED, succeededStatus); - } - - @Test - void testFailureStatusRetrievalLifecycle() { - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.INITIALIZING))).thenReturn(Optional.empty()); - final var beforeInitializingStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.NOT_STARTED, beforeInitializingStatus); - - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.INITIALIZING))).thenReturn(Optional.of("")); - final var initializingStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.INITIALIZING, initializingStatus); - - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.RUNNING))).thenReturn(Optional.of("")); - final var runningStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.RUNNING, runningStatus); - - when(documentStore.read(stateManager.getDocumentStoreKey(AsyncKubePodStatus.FAILED))).thenReturn(Optional.of("output")); - final var failedStatus = stateManager.getStatus(); - assertEquals(AsyncKubePodStatus.FAILED, failedStatus); - } - -} diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/EventListenersTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/EventListenersTest.java deleted file mode 100644 index 5e8ba157f0a15..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/EventListenersTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; - -import io.airbyte.config.EnvConfigs; -import io.airbyte.persistence.job.models.JobRunConfig; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class EventListenersTest { - - private Map envVars; - private EnvConfigs configs; - private JobRunConfig jobRunConfig; - - @BeforeEach - void setup() { - envVars = new HashMap(); - configs = mock(EnvConfigs.class); - jobRunConfig = mock(JobRunConfig.class); - } - - @Test - void setEnvVars() { - envVars = Map.of( - // should be set as it is part of the ENV_VARS_TO_TRANSFER - EnvConfigs.WORKER_ENVIRONMENT, "worker-environment", - // should not be set as it is not part of ENV_VARS_TO_TRANSFER - "RANDOM_ENV", "random-env"); - - final var properties = new HashMap(); - final var listeners = new EventListeners(envVars, configs, jobRunConfig, (name, value) -> { - properties.put(name, value); - return null; - }); - - listeners.setEnvVars(null); - assertEquals(1, properties.size()); - assertEquals("worker-environment", properties.get(EnvConfigs.WORKER_ENVIRONMENT)); - } - -} diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/HeartbeatControllerTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/HeartbeatControllerTest.java deleted file mode 100644 index 40981dd7f1d57..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/HeartbeatControllerTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import io.micronaut.http.HttpRequest; -import io.micronaut.http.client.HttpClient; -import io.micronaut.http.client.annotation.Client; -import io.micronaut.runtime.server.EmbeddedServer; -import io.micronaut.test.extensions.junit5.annotation.MicronautTest; -import jakarta.inject.Inject; -import org.junit.jupiter.api.Test; - -@MicronautTest -class HeartbeatControllerTest { - - @Inject - EmbeddedServer server; - - @Inject - @Client("/") - HttpClient client; - - @Test - void testHeartbeat() { - final var response = client.toBlocking().retrieve(HttpRequest.GET("/")); - assertEquals("{\"up\":true}", response); - } - -} diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ConfigFactoryTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ConfigFactoryTest.java deleted file mode 100644 index 4c4b8fb9b6b39..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ConfigFactoryTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.config; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.workers.process.KubePodInfo; -import io.micronaut.test.extensions.junit5.annotation.MicronautTest; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import java.util.Map; -import org.junit.jupiter.api.Test; - -@MicronautTest -class ConfigFactoryTest { - - @Inject - @Named("configDir") - String configDir; - - @Inject - @Named("application") - String application; - - @Inject - @Named("envVars") - Map envVars; - - @Inject - JobRunConfig jobRunConfig; - - @Inject - KubePodInfo kubePodInfo; - - @Test - void configDir() { - assertEquals("src/test/resources/files", configDir); - } - - @Test - void application() { - assertEquals("normalization-orchestrator", application); - } - - @Test - void envVars() { - assertEquals(29, envVars.size()); - } - - @Test - void jobRunConfig() { - assertEquals("824289", jobRunConfig.getJobId()); - assertEquals(10, jobRunConfig.getAttemptId()); - } - - @Test - void kubePodInfo() { - assertEquals("orchestrator-norm-job-824289-attempt-10", kubePodInfo.name()); - assertEquals("jobs", kubePodInfo.namespace()); - assertEquals("airbyte/container-orchestrator:dev-f0bb7a0ba3", kubePodInfo.mainContainerInfo().image()); - assertEquals("IfNotPresent", kubePodInfo.mainContainerInfo().pullPolicy()); - } - -} diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryK8sTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryK8sTest.java deleted file mode 100644 index 2fbf71e830018..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryK8sTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.config; - -import static org.junit.jupiter.api.Assertions.assertInstanceOf; - -import io.airbyte.workers.process.KubeProcessFactory; -import io.airbyte.workers.process.ProcessFactory; -import io.micronaut.context.env.Environment; -import io.micronaut.test.extensions.junit5.annotation.MicronautTest; -import jakarta.inject.Inject; -import org.junit.jupiter.api.Test; - -@MicronautTest(environments = Environment.KUBERNETES) -class ContainerOrchestratorFactoryK8sTest { - - @Inject - ProcessFactory processFactory; - - @Test - void processFactory() { - assertInstanceOf(KubeProcessFactory.class, processFactory); - } - -} diff --git a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryTest.java b/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryTest.java deleted file mode 100644 index adc93c039602f..0000000000000 --- a/airbyte-container-orchestrator/src/test/java/io/airbyte/container_orchestrator/config/ContainerOrchestratorFactoryTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.container_orchestrator.config; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.airbyte.api.client.generated.DestinationApi; -import io.airbyte.api.client.generated.SourceApi; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.protocol.AirbyteMessageSerDeProvider; -import io.airbyte.commons.protocol.AirbyteProtocolVersionedMigratorFactory; -import io.airbyte.config.EnvConfigs; -import io.airbyte.featureflag.FeatureFlagClient; -import io.airbyte.featureflag.TestClient; -import io.airbyte.persistence.job.models.JobRunConfig; -import io.airbyte.workers.WorkerConfigs; -import io.airbyte.workers.process.AsyncOrchestratorPodProcess; -import io.airbyte.workers.process.DockerProcessFactory; -import io.airbyte.workers.process.ProcessFactory; -import io.airbyte.workers.sync.DbtLauncherWorker; -import io.airbyte.workers.sync.NormalizationLauncherWorker; -import io.airbyte.workers.sync.ReplicationLauncherWorker; -import io.micronaut.context.annotation.Bean; -import io.micronaut.context.annotation.Replaces; -import io.micronaut.test.extensions.junit5.annotation.MicronautTest; -import jakarta.inject.Inject; -import java.util.Map; -import org.junit.jupiter.api.Test; - -@MicronautTest -class ContainerOrchestratorFactoryTest { - - @Inject - FeatureFlags featureFlags; - - @Bean - @Replaces(FeatureFlagClient.class) - FeatureFlagClient featureFlagClient = new TestClient(Map.of()); - - @Inject - EnvConfigs envConfigs; - - @Inject - WorkerConfigs workerConfigs; - - @Inject - ProcessFactory processFactory; - - @Inject - AirbyteMessageSerDeProvider airbyteMessageSerDeProvider; - - @Inject - AirbyteProtocolVersionedMigratorFactory airbyteProtocolVersionedMigratorFactory; - - @Inject - JobRunConfig jobRunConfig; - - @Inject - SourceApi sourceApi; - - @Inject - DestinationApi destinationApi; - - // Tests will fail if this is uncommented, due to how the implementation of the DocumentStoreClient - // is being created - // @Inject - // DocumentStoreClient documentStoreClient; - - @Test - void featureFlags() { - assertNotNull(featureFlags); - } - - @Test - void envConfigs() { - // check one random environment variable to ensure the EnvConfigs was created correctly - assertEquals("/tmp/airbyte_local", envConfigs.getEnv(EnvConfigs.LOCAL_DOCKER_MOUNT)); - } - - @Test - void workerConfigs() { - // check two variables to ensure the WorkerConfig was created correctly - assertEquals("1", workerConfigs.getResourceRequirements().getCpuLimit()); - assertEquals("1Gi", workerConfigs.getResourceRequirements().getMemoryLimit()); - } - - @Test - void processFactory() { - assertInstanceOf(DockerProcessFactory.class, processFactory); - } - - /** - * There isn't an easy way to test the correct JobOrchestrator is injected using @MicronautTest - * with @Nested classes, so opting for the more manual approach. - */ - @Test - void jobOrchestrator() { - final var factory = new ContainerOrchestratorFactory(); - - final var repl = factory.jobOrchestrator( - ReplicationLauncherWorker.REPLICATION, envConfigs, processFactory, featureFlags, featureFlagClient, workerConfigs, - airbyteMessageSerDeProvider, airbyteProtocolVersionedMigratorFactory, jobRunConfig, sourceApi, destinationApi); - assertEquals("Replication", repl.getOrchestratorName()); - - final var norm = factory.jobOrchestrator( - NormalizationLauncherWorker.NORMALIZATION, envConfigs, processFactory, featureFlags, featureFlagClient, workerConfigs, - airbyteMessageSerDeProvider, airbyteProtocolVersionedMigratorFactory, jobRunConfig, sourceApi, destinationApi); - assertEquals("Normalization", norm.getOrchestratorName()); - - final var dbt = factory.jobOrchestrator( - DbtLauncherWorker.DBT, envConfigs, processFactory, featureFlags, featureFlagClient, workerConfigs, - airbyteMessageSerDeProvider, airbyteProtocolVersionedMigratorFactory, jobRunConfig, sourceApi, destinationApi); - assertEquals("DBT Transformation", dbt.getOrchestratorName()); - - final var noop = factory.jobOrchestrator( - AsyncOrchestratorPodProcess.NO_OP, envConfigs, processFactory, featureFlags, featureFlagClient, workerConfigs, - airbyteMessageSerDeProvider, airbyteProtocolVersionedMigratorFactory, jobRunConfig, sourceApi, destinationApi); - assertEquals("NO_OP", noop.getOrchestratorName()); - - var caught = false; - try { - factory.jobOrchestrator( - "does not exist", envConfigs, processFactory, featureFlags, featureFlagClient, workerConfigs, - airbyteMessageSerDeProvider, airbyteProtocolVersionedMigratorFactory, jobRunConfig, sourceApi, destinationApi); - } catch (final Exception e) { - caught = true; - } - assertTrue(caught, "invalid application name should have thrown an exception"); - } - -} diff --git a/airbyte-container-orchestrator/src/test/resources/application.yml b/airbyte-container-orchestrator/src/test/resources/application.yml deleted file mode 100644 index b789c4757d51c..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/application.yml +++ /dev/null @@ -1,23 +0,0 @@ -micronaut: - server: - port: 9000 - -airbyte: - acceptance: - test: - enabled: false - config-dir: src/test/resources/files - control: - plane: - auth-endpoint: "" - data: - plane: - service-account: - credentials-path: "" - email: "" - internal: - api: - auth-header: - name: "" - value: "" - host: airbyte-server-svc:8001 \ No newline at end of file diff --git a/airbyte-container-orchestrator/src/test/resources/files/KUBE_POD_INFO b/airbyte-container-orchestrator/src/test/resources/files/KUBE_POD_INFO deleted file mode 100644 index 4d1363f4d3b66..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/files/KUBE_POD_INFO +++ /dev/null @@ -1,8 +0,0 @@ -{ - "namespace": "jobs", - "name": "orchestrator-norm-job-824289-attempt-10", - "mainContainerInfo": { - "image": "airbyte/container-orchestrator:dev-f0bb7a0ba3", - "pullPolicy": "IfNotPresent" - } -} \ No newline at end of file diff --git a/airbyte-container-orchestrator/src/test/resources/files/application.txt b/airbyte-container-orchestrator/src/test/resources/files/application.txt deleted file mode 100644 index db208313a1f18..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/files/application.txt +++ /dev/null @@ -1 +0,0 @@ -normalization-orchestrator \ No newline at end of file diff --git a/airbyte-container-orchestrator/src/test/resources/files/destinationLauncherConfig.json b/airbyte-container-orchestrator/src/test/resources/files/destinationLauncherConfig.json deleted file mode 100644 index 2673a94128d86..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/files/destinationLauncherConfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "jobId": "824289", - "attemptId": 10, - "dockerImage": "airbyte/destination-postgres-strict-encrypt:0.3.26", - "protocolVersion": { - "version": "0.2.0" - } -} diff --git a/airbyte-container-orchestrator/src/test/resources/files/envMap.json b/airbyte-container-orchestrator/src/test/resources/files/envMap.json deleted file mode 100644 index 485382509ea8d..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/files/envMap.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "PUBLISH_METRICS": "true", - "LOCAL_DOCKER_MOUNT": "/tmp/airbyte_local", - "JOB_MAIN_CONTAINER_CPU_LIMIT": "1", - "AWS_SECRET_ACCESS_KEY": "secret-access-key", - "JOB_KUBE_NAMESPACE": "jobs", - "GOOGLE_APPLICATION_CREDENTIALS": "src/test/resources/files/creds.json", - "STATE_STORAGE_GCS_APPLICATION_CREDENTIALS": "src/test/resources/files/app-creds.json", - "S3_MINIO_ENDPOINT": " ", - "USE_STREAM_CAPABLE_STATE": "true", - "WORKER_ENVIRONMENT": "KUBERNETES", - "AWS_ACCESS_KEY_ID": "access-key-id", - "JOB_MAIN_CONTAINER_MEMORY_REQUEST": "1Gi", - "WORKSPACE_ROOT": "/workspace", - "METRIC_CLIENT": "imperial", - "LOG_LEVEL": "INFO", - "DEPLOYMENT_MODE": "CLOUD", - "JOB_KUBE_NODE_SELECTORS": "node-selectors", - "JOB_MAIN_CONTAINER_MEMORY_LIMIT": "1Gi", - "DD_DOGSTATSD_PORT": "8125", - "DD_AGENT_HOST": "172.20.100.45", - "S3_LOG_BUCKET_REGION": " ", - "GCS_LOG_BUCKET": "logs", - "STATE_STORAGE_GCS_BUCKET_NAME": "storage", - "S3_PATH_STYLE_ACCESS": " ", - "LOCAL_ROOT": "/tmp/airbyte_local", - "WORKSPACE_DOCKER_MOUNT": "workspace", - "JOB_MAIN_CONTAINER_CPU_REQUEST": "1", - "S3_LOG_BUCKET": " ", - "AIRBYTE_VERSION": "dev-hashhash-env" -} diff --git a/airbyte-container-orchestrator/src/test/resources/files/input.json b/airbyte-container-orchestrator/src/test/resources/files/input.json deleted file mode 100644 index 5a3230f16fee6..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/files/input.json +++ /dev/null @@ -1,162 +0,0 @@ -{ - "destinationConfiguration": { - "host": "example.us-east-2.rds.amazonaws.com", - "port": 5432, - "schema": "public", - "database": "example", - "password": "dmVyeXN0cm9uZ3Bhc3N3b3Jk", - "ssl_mode": { - "mode": "require" - }, - "username": "legit-user", - "tunnel_method": { - "tunnel_method": "NO_TUNNEL" - } - }, - "catalog": { - "streams": [ - { - "stream": { - "name": "example", - "json_schema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "logs": { - "type": "string" - }, - "checksum": { - "type": "string" - }, - "started_at": { - "type": "string", - "format": "date-time", - "airbyte_type": "timestamp_with_timezone" - }, - "finished_at": { - "type": "string", - "format": "date-time", - "airbyte_type": "timestamp_with_timezone" - }, - "migration_name": { - "type": "string" - }, - "rolled_back_at": { - "type": "string", - "format": "date-time", - "airbyte_type": "timestamp_with_timezone" - }, - "applied_steps_count": { - "type": "number", - "airbyte_type": "integer" - } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [], - "source_defined_primary_key": [["id"]], - "namespace": "events" - }, - "sync_mode": "full_refresh", - "cursor_field": [], - "destination_sync_mode": "overwrite", - "primary_key": [["id"]] - }, - { - "stream": { - "name": "example", - "json_schema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "event": { - "type": "string" - }, - "context": { - "type": "string" - }, - "sent_at": { - "type": "string", - "format": "date-time", - "airbyte_type": "timestamp_without_timezone" - }, - "user_id": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "airbyte_type": "timestamp_without_timezone" - }, - "message_id": { - "type": "string" - }, - "properties": { - "type": "string" - }, - "anonymous_id": { - "type": "string" - }, - "integrations": { - "type": "string" - } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [], - "source_defined_primary_key": [["id"]], - "namespace": "events" - }, - "sync_mode": "incremental", - "cursor_field": ["timestamp"], - "destination_sync_mode": "append_dedup", - "primary_key": [["id"]] - }, - { - "stream": { - "name": "example", - "json_schema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "doc_id": { - "type": "string" - }, - "event_id": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "airbyte_type": "timestamp_without_timezone" - } - } - }, - "supported_sync_modes": ["full_refresh", "incremental"], - "default_cursor_field": [], - "source_defined_primary_key": [["id"]], - "namespace": "events" - }, - "sync_mode": "incremental", - "cursor_field": ["timestamp"], - "destination_sync_mode": "append_dedup", - "primary_key": [["id"]] - } - ] - }, - "resourceRequirements": { - "cpu_request": "", - "cpu_limit": "", - "memory_request": "1.5Gi", - "memory_limit": "1.5Gi" - } -} diff --git a/airbyte-container-orchestrator/src/test/resources/files/jobRunConfig.json b/airbyte-container-orchestrator/src/test/resources/files/jobRunConfig.json deleted file mode 100644 index e06b6a368a5fe..0000000000000 --- a/airbyte-container-orchestrator/src/test/resources/files/jobRunConfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "jobId": "824289", - "attemptId": 10 -} diff --git a/airbyte-cron/Dockerfile b/airbyte-cron/Dockerfile deleted file mode 100644 index 2cbb772912b8e..0000000000000 --- a/airbyte-cron/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -ARG JDK_IMAGE=airbyte/airbyte-base-java-image:1.0 -FROM ${JDK_IMAGE} AS cron - -ARG VERSION=0.40.32 - -ENV APPLICATION airbyte-cron -ENV VERSION ${VERSION} - -WORKDIR /app - -# This is automatically unzipped by Docker -ADD bin/${APPLICATION}-${VERSION}.tar /app - -# wait for upstream dependencies to become available before starting server -ENTRYPOINT ["/bin/bash", "-c", "${APPLICATION}-${VERSION}/bin/${APPLICATION}"] diff --git a/airbyte-cron/LICENSE b/airbyte-cron/LICENSE deleted file mode 100644 index 7d1808d83342e..0000000000000 --- a/airbyte-cron/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Airbyte, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/airbyte-cron/build.gradle b/airbyte-cron/build.gradle deleted file mode 100644 index 47c1c939a2ed2..0000000000000 --- a/airbyte-cron/build.gradle +++ /dev/null @@ -1,52 +0,0 @@ -plugins { - id 'application' -} - -dependencies { - implementation 'com.auth0:java-jwt:3.19.2' - implementation 'io.fabric8:kubernetes-client:5.12.2' - implementation 'io.sentry:sentry:6.3.1' - implementation libs.bundles.temporal - implementation libs.bundles.datadog - - implementation project(':airbyte-api') - implementation project(':airbyte-analytics') - implementation project(':airbyte-commons-temporal') - implementation project(':airbyte-config:config-models') - implementation project(':airbyte-config:config-persistence') - implementation project(':airbyte-config:init') - implementation project(':airbyte-json-validation') - implementation project(':airbyte-db:db-lib') - implementation project(':airbyte-metrics:metrics-lib') - implementation project(':airbyte-persistence:job-persistence') - - annotationProcessor platform(libs.micronaut.bom) - annotationProcessor libs.bundles.micronaut.annotation.processor - - implementation platform(libs.micronaut.bom) - implementation libs.bundles.micronaut -} - -mainClassName = 'io.airbyte.cron.MicronautCronRunner' - -application { - mainClass = mainClassName - applicationDefaultJvmArgs = ['-XX:+ExitOnOutOfMemoryError', '-XX:MaxRAMPercentage=75.0'] -} - -Properties env = new Properties() -rootProject.file('.env.dev').withInputStream { env.load(it) } - -run { - // default for running on local machine. - env.each { entry -> - environment entry.getKey(), entry.getValue() - } - - environment 'AIRBYTE_ROLE', System.getenv('AIRBYTE_ROLE') - environment 'AIRBYTE_VERSION', env.VERSION -} - -tasks.named("buildDockerImage") { - dependsOn copyGeneratedTar -} diff --git a/airbyte-cron/gradle.properties b/airbyte-cron/gradle.properties deleted file mode 100644 index fe63d1ca9ce4f..0000000000000 --- a/airbyte-cron/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=cron diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/ApplicationInitializer.java b/airbyte-cron/src/main/java/io/airbyte/cron/ApplicationInitializer.java deleted file mode 100644 index f5460f582a6fc..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/ApplicationInitializer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron; - -import io.airbyte.commons.temporal.TemporalInitializationUtils; -import io.micronaut.context.event.ApplicationEventListener; -import io.micronaut.discovery.event.ServiceReadyEvent; -import jakarta.inject.Inject; - -public class ApplicationInitializer implements ApplicationEventListener { - - @Inject - private TemporalInitializationUtils temporalInitializationUtils; - - @Override - public void onApplicationEvent(ServiceReadyEvent event) { - temporalInitializationUtils.waitForTemporalNamespace(); - } - -} diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/MicronautCronRunner.java b/airbyte-cron/src/main/java/io/airbyte/cron/MicronautCronRunner.java deleted file mode 100644 index 1f6ff6088af85..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/MicronautCronRunner.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron; - -import io.micronaut.runtime.Micronaut; - -/** - * Micronaut server responsible of running scheduled method. The methods need to be separated in - * Bean based on what they are cleaning and contain a method annotated with `@Scheduled` - * - * Injected object looks unused but they are not - */ -public class MicronautCronRunner { - - public static final String SCHEDULED_TRACE_OPERATION_NAME = "scheduled"; - - public static void main(final String[] args) { - Micronaut.build(args) - .mainClass(MicronautCronRunner.class) - .start(); - } - -} diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/config/ApplicationBeanFactory.java b/airbyte-cron/src/main/java/io/airbyte/cron/config/ApplicationBeanFactory.java deleted file mode 100644 index 065bdd9affcd1..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/config/ApplicationBeanFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron.config; - -import io.airbyte.config.Configs.DeploymentMode; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import io.micronaut.core.util.StringUtils; -import jakarta.inject.Singleton; -import java.util.Locale; -import java.util.function.Function; -import lombok.extern.slf4j.Slf4j; - -/** - * Micronaut bean factory for general singletons. - */ -@Factory -@Slf4j -public class ApplicationBeanFactory { - - @Singleton - public DeploymentMode deploymentMode(@Value("${airbyte.deployment-mode}") final String deploymentMode) { - return convertToEnum(deploymentMode, DeploymentMode::valueOf, DeploymentMode.OSS); - } - - @Singleton - public JsonSecretsProcessor jsonSecretsProcessor() { - return JsonSecretsProcessor.builder() - .copySecrets(false) - .build(); - } - - private T convertToEnum(final String value, final Function creatorFunction, final T defaultValue) { - return StringUtils.isNotEmpty(value) ? creatorFunction.apply(value.toUpperCase(Locale.ROOT)) : defaultValue; - } - -} diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/config/DatabaseBeanFactory.java b/airbyte-cron/src/main/java/io/airbyte/cron/config/DatabaseBeanFactory.java deleted file mode 100644 index 52928acc1f7cb..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/config/DatabaseBeanFactory.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron.config; - -import io.airbyte.commons.temporal.config.WorkerMode; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.StreamResetPersistence; -import io.airbyte.db.Database; -import io.airbyte.db.check.DatabaseMigrationCheck; -import io.airbyte.db.factory.DatabaseCheckFactory; -import io.airbyte.persistence.job.DefaultJobPersistence; -import io.airbyte.persistence.job.JobPersistence; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.annotation.Value; -import io.micronaut.flyway.FlywayConfigurationProperties; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import javax.sql.DataSource; -import lombok.extern.slf4j.Slf4j; -import org.flywaydb.core.Flyway; -import org.jooq.DSLContext; - -/** - * Micronaut bean factory for database-related singletons. - */ -@Factory -@Slf4j -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class DatabaseBeanFactory { - - private static final String BASELINE_DESCRIPTION = "Baseline from file-based migration v1"; - private static final Boolean BASELINE_ON_MIGRATION = true; - private static final String INSTALLED_BY = "AirbyteCron"; - - @Singleton - @Named("configDatabase") - public Database configDatabase(@Named("config") final DSLContext dslContext) throws IOException { - return new Database(dslContext); - } - - @Singleton - @Requires(env = WorkerMode.CONTROL_PLANE) - @Named("jobsDatabase") - public Database jobsDatabase(@Named("jobs") final DSLContext dslContext) throws IOException { - return new Database(dslContext); - } - - @Singleton - @Named("configFlyway") - public Flyway configFlyway(@Named("config") final FlywayConfigurationProperties configFlywayConfigurationProperties, - @Named("config") final DataSource configDataSource, - @Value("${airbyte.flyway.configs.minimum-migration-version}") final String baselineVersion) { - return configFlywayConfigurationProperties.getFluentConfiguration() - .dataSource(configDataSource) - .baselineVersion(baselineVersion) - .baselineDescription(BASELINE_DESCRIPTION) - .baselineOnMigrate(BASELINE_ON_MIGRATION) - .installedBy(INSTALLED_BY) - .table(String.format("airbyte_%s_migrations", "configs")) - .load(); - } - - @Singleton - public ConfigRepository configRepository(@Named("configDatabase") final Database configDatabase) { - return new ConfigRepository(configDatabase); - } - - @Singleton - @Named("configsDatabaseMigrationCheck") - public DatabaseMigrationCheck configsDatabaseMigrationCheck(@Named("config") final DSLContext dslContext, - @Named("configFlyway") final Flyway configsFlyway, - @Value("${airbyte.flyway.configs.minimum-migration-version}") final String configsDatabaseMinimumFlywayMigrationVersion, - @Value("${airbyte.flyway.configs.initialization-timeout-ms}") final Long configsDatabaseInitializationTimeoutMs) { - log.info("Configs database configuration: {} {}", configsDatabaseMinimumFlywayMigrationVersion, configsDatabaseInitializationTimeoutMs); - return DatabaseCheckFactory - .createConfigsDatabaseMigrationCheck(dslContext, configsFlyway, configsDatabaseMinimumFlywayMigrationVersion, - configsDatabaseInitializationTimeoutMs); - } - - @Singleton - @Requires(env = WorkerMode.CONTROL_PLANE) - public StreamResetPersistence streamResetPersistence(@Named("configDatabase") final Database configDatabase) { - return new StreamResetPersistence(configDatabase); - } - - @Singleton - @Requires(env = WorkerMode.CONTROL_PLANE) - public JobPersistence jobPersistence(@Named("jobsDatabase") final Database jobDatabase) { - return new DefaultJobPersistence(jobDatabase); - } - -} diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/DefinitionsUpdater.java b/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/DefinitionsUpdater.java deleted file mode 100644 index 5821fa0844d2a..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/DefinitionsUpdater.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron.selfhealing; - -import static io.airbyte.cron.MicronautCronRunner.SCHEDULED_TRACE_OPERATION_NAME; - -import datadog.trace.api.Trace; -import io.airbyte.config.Configs.DeploymentMode; -import io.airbyte.config.init.ApplyDefinitionsHelper; -import io.micronaut.context.annotation.Requires; -import io.micronaut.scheduling.annotation.Scheduled; -import jakarta.inject.Singleton; -import lombok.extern.slf4j.Slf4j; - -/** - * DefinitionsUpdater - * - * Automatically updates connector definitions from a remote catalog at an interval (30s). This can - * be enabled by setting a REMOTE_CATALOG_URL and UPDATE_DEFINITIONS_CRON_ENABLED=true. - */ -@Singleton -@Slf4j -@Requires(property = "airbyte.cron.update-definitions.enabled", - value = "true") -public class DefinitionsUpdater { - - private final ApplyDefinitionsHelper applyDefinitionsHelper; - private final DeploymentMode deploymentMode; - - public DefinitionsUpdater(final ApplyDefinitionsHelper applyDefinitionsHelper, - final DeploymentMode deploymentMode) { - log.info("Creating connector definitions updater"); - - this.applyDefinitionsHelper = applyDefinitionsHelper; - this.deploymentMode = deploymentMode; - } - - @Trace(operationName = SCHEDULED_TRACE_OPERATION_NAME) - @Scheduled(fixedRate = "30s", - initialDelay = "1m") - void updateDefinitions() { - log.info("Updating definitions..."); - - try { - try { - applyDefinitionsHelper.apply(deploymentMode == DeploymentMode.CLOUD); - - log.info("Done applying remote connector definitions"); - } catch (final Exception e) { - log.error("Error while applying remote definitions", e); - } - - } catch (final Exception e) { - log.error("Error when retrieving remote definitions", e); - } - - } - -} diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/Temporal.java b/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/Temporal.java deleted file mode 100644 index 013775de8c265..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/Temporal.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron.selfhealing; - -import static io.airbyte.cron.MicronautCronRunner.SCHEDULED_TRACE_OPERATION_NAME; - -import datadog.trace.api.Trace; -import io.airbyte.commons.temporal.TemporalClient; -import io.micronaut.scheduling.annotation.Scheduled; -import io.temporal.api.enums.v1.WorkflowExecutionStatus; -import jakarta.inject.Singleton; -import lombok.extern.slf4j.Slf4j; - -@Singleton -@Slf4j -public class Temporal { - - private final TemporalClient temporalClient; - - public Temporal(final TemporalClient temporalClient) { - log.debug("Creating temporal self-healing"); - this.temporalClient = temporalClient; - } - - @Trace(operationName = SCHEDULED_TRACE_OPERATION_NAME) - @Scheduled(fixedRate = "10s") - void cleanTemporal() { - temporalClient.restartClosedWorkflowByStatus(WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED); - } - -} diff --git a/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/WorkspaceCleaner.java b/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/WorkspaceCleaner.java deleted file mode 100644 index 5db869dd4c3dd..0000000000000 --- a/airbyte-cron/src/main/java/io/airbyte/cron/selfhealing/WorkspaceCleaner.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.cron.selfhealing; - -import static io.airbyte.cron.MicronautCronRunner.SCHEDULED_TRACE_OPERATION_NAME; - -import datadog.trace.api.Trace; -import io.airbyte.config.Configs; -import io.airbyte.config.EnvConfigs; -import io.airbyte.metrics.lib.ApmTraceUtils; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.env.Environment; -import io.micronaut.scheduling.annotation.Scheduled; -import jakarta.inject.Singleton; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.util.Date; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.filefilter.AgeFileFilter; - -@Singleton -@Slf4j -@Requires(notEnv = Environment.KUBERNETES) -public class WorkspaceCleaner { - - private final Path workspaceRoot; - private final long maxAgeFilesInDays; - - WorkspaceCleaner() { - log.info("Creating workspace cleaner"); - - // TODO Configs should get injected through micronaut - final Configs configs = new EnvConfigs(); - - this.workspaceRoot = configs.getWorkspaceRoot(); - // We align max file age on temporal for history consistency - // It might make sense configure this independently in the future - this.maxAgeFilesInDays = configs.getTemporalRetentionInDays(); - } - - /* - * Delete files older than maxAgeFilesInDays from the workspace - * - * NOTE: this is currently only intended to work for docker - */ - @Trace(operationName = SCHEDULED_TRACE_OPERATION_NAME) - @Scheduled(fixedRate = "1d") - public void deleteOldFiles() throws IOException { - final Date oldestAllowed = getDateFromDaysAgo(maxAgeFilesInDays); - log.info("Deleting files older than {} days ({})", maxAgeFilesInDays, oldestAllowed); - - ApmTraceUtils.addTagsToTrace(Map.of("oldest_date_allowed", oldestAllowed, "max_age", maxAgeFilesInDays)); - - final AtomicInteger counter = new AtomicInteger(0); - Files.walk(workspaceRoot) - .map(Path::toFile) - .filter(f -> new AgeFileFilter(oldestAllowed).accept(f)) - .forEach(file -> { - log.debug("Deleting file: " + file.toString()); - FileUtils.deleteQuietly(file); - counter.incrementAndGet(); - final File parentDir = file.getParentFile(); - if (parentDir.isDirectory() && parentDir.listFiles().length == 0) { - FileUtils.deleteQuietly(parentDir); - } - }); - log.info("deleted {} files", counter.get()); - } - - private static Date getDateFromDaysAgo(final long daysAgo) { - return Date.from(LocalDateTime.now().minusDays(daysAgo).toInstant(OffsetDateTime.now().getOffset())); - } - -} diff --git a/airbyte-cron/src/main/resources/application.yml b/airbyte-cron/src/main/resources/application.yml deleted file mode 100644 index 05bf160cd95e8..0000000000000 --- a/airbyte-cron/src/main/resources/application.yml +++ /dev/null @@ -1,127 +0,0 @@ -micronaut: - application: - name: airbyte-cron - caches: - remote-definitions-provider: - expire-after-write: 15s - server: - port: 9001 - -airbyte: - cron: - update-definitions: - enabled: ${UPDATE_DEFINITIONS_CRON_ENABLED:false} - deployment-mode: ${DEPLOYMENT_MODE:OSS} - flyway: - configs: - initialization-timeout-ms: ${CONFIGS_DATABASE_INITIALIZATION_TIMEOUT_MS:60000} - minimum-migration-version: ${CONFIGS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION} - local: - docker-mount: ${LOCAL_DOCKER_MOUNT:} - root: ${LOCAL_ROOT} - platform: - remote-connector-catalog: - timeout-ms: ${REMOTE_CONNECTOR_CATALOG_MS:30000} - url: ${REMOTE_CONNECTOR_CATALOG_URL:} - role: ${AIRBYTE_ROLE:} - temporal: - worker: - ports: ${TEMPORAL_WORKER_PORTS:} - tracking-strategy: ${TRACKING_STRATEGY:LOGGING} - version: ${AIRBYTE_VERSION} - workflow: - failure: - restart-delay: ${WORKFLOW_FAILURE_RESTART_DELAY_SECONDS:600} - workspace: - docker-mount: ${WORKSPACE_DOCKER_MOUNT:} - root: ${WORKSPACE_ROOT} - -datasources: - config: - connection-test-query: SELECT 1 - connection-timeout: 30000 - idle-timeout: 600000 - initialization-fail-timeout: -1 # Disable fail fast checking to avoid issues due to other pods not being started in time - maximum-pool-size: 5 - minimum-idle: 0 - url: ${DATABASE_URL} - driverClassName: org.postgresql.Driver - username: ${DATABASE_USER} - password: ${DATABASE_PASSWORD} - jobs: - connection-test-query: SELECT 1 - connection-timeout: 30000 - idle-timeout: 600000 - initialization-fail-timeout: -1 # Disable fail fast checking to avoid issues due to other pods not being started in time - maximum-pool-size: 5 - minimum-idle: 0 - url: ${DATABASE_URL} - driverClassName: org.postgresql.Driver - username: ${DATABASE_USER} - password: ${DATABASE_PASSWORD} - -docker: - network: ${DOCKER_NETWORK:host} - -endpoints: - beans: - enabled: true - sensitive: false - env: - enabled: true - sensitive: false - health: - enabled: true - sensitive: false - info: - enabled: true - sensitive: true - loggers: - enabled: true - sensitive: true - refresh: - enabled: false - sensitive: true - routes: - enabled: true - sensitive: false - threaddump: - enabled: true - sensitive: true - -flyway: - enabled: true - datasources: - config: - enabled: false - locations: - - 'classpath:io/airbyte/db/instance/configs/migrations' - jobs: - enabled: false - locations: - - 'classpath:io/airbyte/db/instance/jobs/migrations' - -jooq: - datasources: - config: - jackson-converter-enabled: true - sql-dialect: POSTGRES - jobs: - jackson-converter-enabled: true - sql-dialect: POSTGRES - -temporal: - cloud: - client: - cert: ${TEMPORAL_CLOUD_CLIENT_CERT:} - key: ${TEMPORAL_CLOUD_CLIENT_KEY:} - enabled: ${TEMPORAL_CLOUD_ENABLED:false} - host: ${TEMPORAL_CLOUD_HOST:} - namespace: ${TEMPORAL_CLOUD_NAMESPACE:} - host: ${TEMPORAL_HOST:`airbyte-temporal:7233`} - retention: ${TEMPORAL_HISTORY_RETENTION_IN_DAYS:30} - -logger: - levels: -# Uncomment to help resolve issues with conditional beans -# io.micronaut.context.condition: DEBUG diff --git a/airbyte-cron/src/main/resources/micronaut-banner.txt b/airbyte-cron/src/main/resources/micronaut-banner.txt deleted file mode 100644 index d7778fa0cb046..0000000000000 --- a/airbyte-cron/src/main/resources/micronaut-banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - - ___ _ __ __ - / | (_)____/ /_ __ __/ /____ - / /| | / / ___/ __ \/ / / / __/ _ \ - / ___ |/ / / / /_/ / /_/ / /_/ __/ -/_/ |_/_/_/ /_.___/\__, /\__/\___/ - /____/ - : airbyte-cron : \ No newline at end of file diff --git a/airbyte-metrics/reporter/Dockerfile b/airbyte-metrics/reporter/Dockerfile deleted file mode 100644 index 0cfbeddb00afc..0000000000000 --- a/airbyte-metrics/reporter/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -ARG JDK_IMAGE=airbyte/airbyte-base-java-image:1.0 -FROM ${JDK_IMAGE} AS metrics-reporter - -ARG VERSION=0.40.32 - -ENV APPLICATION airbyte-metrics-reporter -ENV VERSION ${VERSION} - -WORKDIR /app - -ADD bin/${APPLICATION}-${VERSION}.tar /app - - -# wait for upstream dependencies to become available before starting server -ENTRYPOINT ["/bin/bash", "-c", "${APPLICATION}-${VERSION}/bin/${APPLICATION}"] diff --git a/airbyte-metrics/reporter/README.md b/airbyte-metrics/reporter/README.md deleted file mode 100644 index 7457369055062..0000000000000 --- a/airbyte-metrics/reporter/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## Airbyte Metrics Reporter - -The Reporter attempts to keep code clean by centralising metric calculation and submissions. - -This is primarily intended for Airbyte Cloud, though OSS users are certainly welcome to make use of this. diff --git a/airbyte-metrics/reporter/build.gradle b/airbyte-metrics/reporter/build.gradle deleted file mode 100644 index 22885a77de9f8..0000000000000 --- a/airbyte-metrics/reporter/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -plugins { - id 'application' -} - -configurations { - jdbc -} - -dependencies { - annotationProcessor platform(libs.micronaut.bom) - annotationProcessor libs.bundles.micronaut.annotation.processor - - implementation platform(libs.micronaut.bom) - implementation libs.bundles.micronaut - - implementation project(':airbyte-config:config-models') - implementation project(':airbyte-db:jooq') - implementation project(':airbyte-db:db-lib') - implementation project(':airbyte-metrics:metrics-lib') - - implementation(libs.jooq) { - force = true - } - - testAnnotationProcessor platform(libs.micronaut.bom) - testAnnotationProcessor libs.bundles.micronaut.test.annotation.processor - - testImplementation project(':airbyte-test-utils') - testImplementation libs.bundles.micronaut.test - testImplementation libs.postgresql - testImplementation libs.platform.testcontainers.postgresql -} - -application { - applicationName = "airbyte-metrics-reporter" - mainClass = 'io.airbyte.metrics.reporter.Application' - applicationDefaultJvmArgs = ['-XX:+ExitOnOutOfMemoryError', '-XX:MaxRAMPercentage=75.0'] -} - -tasks.named("buildDockerImage") { - dependsOn copyGeneratedTar -} diff --git a/airbyte-metrics/reporter/gradle.properties b/airbyte-metrics/reporter/gradle.properties deleted file mode 100644 index ce3ec4d9f7a5f..0000000000000 --- a/airbyte-metrics/reporter/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=metrics-reporter diff --git a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Application.java b/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Application.java deleted file mode 100644 index 76ff91e9f1bcf..0000000000000 --- a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Application.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import io.airbyte.metrics.lib.MetricClientFactory; -import io.airbyte.metrics.lib.MetricEmittingApps; -import io.micronaut.runtime.Micronaut; - -/** - * Metric Reporter application. - *

- * Responsible for emitting metric information on a periodic basis. - */ -public class Application { - - public static void main(final String[] args) { - MetricClientFactory.initialize(MetricEmittingApps.METRICS_REPORTER); - Micronaut.run(Application.class, args); - } - -} diff --git a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Emitter.java b/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Emitter.java deleted file mode 100644 index c375603995be7..0000000000000 --- a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/Emitter.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import io.airbyte.metrics.lib.MetricAttribute; -import io.airbyte.metrics.lib.MetricClient; -import io.airbyte.metrics.lib.MetricTags; -import io.airbyte.metrics.lib.OssMetricsRegistry; -import jakarta.inject.Singleton; -import java.lang.invoke.MethodHandles; -import java.time.Duration; -import java.util.concurrent.Callable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -final class NumPendingJobs extends Emitter { - - public NumPendingJobs(final MetricClient client, final MetricRepository db) { - super(client, () -> { - db.numberOfPendingJobsByGeography().forEach((geography, count) -> client.gauge( - OssMetricsRegistry.NUM_PENDING_JOBS, - count, - new MetricAttribute(MetricTags.GEOGRAPHY, geography))); - - return null; - }); - } - -} - -@Singleton -final class NumRunningJobs extends Emitter { - - public NumRunningJobs(final MetricClient client, final MetricRepository db) { - super(client, () -> { - db.numberOfRunningJobsByTaskQueue().forEach((attemptQueue, count) -> client.gauge( - OssMetricsRegistry.NUM_RUNNING_JOBS, - count, - new MetricAttribute(MetricTags.ATTEMPT_QUEUE, attemptQueue))); - return null; - }); - } - -} - -@Singleton -final class NumOrphanRunningJobs extends Emitter { - - NumOrphanRunningJobs(final MetricClient client, final MetricRepository db) { - super(client, () -> { - final var orphaned = db.numberOfOrphanRunningJobs(); - client.gauge(OssMetricsRegistry.NUM_ORPHAN_RUNNING_JOBS, orphaned); - return null; - }); - } - -} - -@Singleton -final class OldestRunningJob extends Emitter { - - OldestRunningJob(final MetricClient client, final MetricRepository db) { - super(client, () -> { - db.oldestRunningJobAgeSecsByTaskQueue().forEach((attemptQueue, count) -> client.gauge( - OssMetricsRegistry.OLDEST_RUNNING_JOB_AGE_SECS, - count, - new MetricAttribute(MetricTags.ATTEMPT_QUEUE, attemptQueue))); - return null; - }); - } - -} - -@Singleton -final class OldestPendingJob extends Emitter { - - OldestPendingJob(final MetricClient client, final MetricRepository db) { - super(client, () -> { - db.oldestPendingJobAgeSecsByGeography().forEach((geographyType, count) -> client.gauge( - OssMetricsRegistry.OLDEST_PENDING_JOB_AGE_SECS, - count, - new MetricAttribute(MetricTags.GEOGRAPHY, geographyType))); - return null; - }); - } - -} - -@Singleton -final class NumActiveConnectionsPerWorkspace extends Emitter { - - NumActiveConnectionsPerWorkspace(final MetricClient client, final MetricRepository db) { - super(client, () -> { - final var workspaceConns = db.numberOfActiveConnPerWorkspace(); - for (final long numCons : workspaceConns) { - client.distribution(OssMetricsRegistry.NUM_ACTIVE_CONN_PER_WORKSPACE, numCons); - } - return null; - }); - } - -} - -@Singleton -final class NumAbnormalScheduledSyncs extends Emitter { - - NumAbnormalScheduledSyncs(final MetricClient client, final MetricRepository db) { - super(client, () -> { - final var count = db.numberOfJobsNotRunningOnScheduleInLastDay(); - client.gauge(OssMetricsRegistry.NUM_ABNORMAL_SCHEDULED_SYNCS_IN_LAST_DAY, count); - return null; - }); - } - - @Override - public Duration getDuration() { - return Duration.ofHours(1); - } - -} - -@Singleton -final class NumUnusuallyLongSyncs extends Emitter { - - NumUnusuallyLongSyncs(final MetricClient client, final MetricRepository db) { - super(client, () -> { - final var count = db.numberOfJobsRunningUnusuallyLong(); - client.gauge(OssMetricsRegistry.NUM_UNUSUALLY_LONG_SYNCS, count); - return null; - }); - } - - @Override - public Duration getDuration() { - return Duration.ofMinutes(15); - } - -} - -@Singleton -final class TotalScheduledSyncs extends Emitter { - - TotalScheduledSyncs(final MetricClient client, final MetricRepository db) { - super(client, () -> { - final var count = db.numScheduledActiveConnectionsInLastDay(); - client.gauge(OssMetricsRegistry.NUM_TOTAL_SCHEDULED_SYNCS_IN_LAST_DAY, count); - return null; - }); - } - - @Override - public Duration getDuration() { - return Duration.ofHours(1); - } - -} - -@Singleton -final class TotalJobRuntimeByTerminalState extends Emitter { - - public TotalJobRuntimeByTerminalState(final MetricClient client, final MetricRepository db) { - super(client, () -> { - db.overallJobRuntimeForTerminalJobsInLastHour() - .forEach((jobStatus, time) -> client.distribution( - OssMetricsRegistry.OVERALL_JOB_RUNTIME_IN_LAST_HOUR_BY_TERMINAL_STATE_SECS, - time, - new MetricAttribute(MetricTags.JOB_STATUS, jobStatus.getLiteral()))); - return null; - }); - } - - @Override - public Duration getDuration() { - return Duration.ofHours(1); - } - -} - -/** - * Abstract base class for all emitted metrics. - *

- * As this is a sealed class, all implementations of it are contained within this same file. - */ -sealed class Emitter { - - protected static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - protected final MetricClient client; - protected final Callable callable; - - Emitter(final MetricClient client, final Callable callable) { - this.client = client; - this.callable = callable; - } - - /** - * Emit the metrics by calling the callable. - *

- * Any exception thrown by the callable will be logged. - * - * @TODO: replace log message with a published error-event of some kind. - */ - public void Emit() { - try { - callable.call(); - client.count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } catch (final Exception e) { - log.error("Exception querying database for metric: ", e); - } - } - - /** - * How often this metric should report, defaults to 15s if not overwritten. - * - * @return Duration of how often this metric should report. - */ - public Duration getDuration() { - return Duration.ofSeconds(15); - } - -} diff --git a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/EventListeners.java b/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/EventListeners.java deleted file mode 100644 index 60375e1f77321..0000000000000 --- a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/EventListeners.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import io.micronaut.runtime.event.ApplicationShutdownEvent; -import io.micronaut.runtime.event.ApplicationStartupEvent; -import io.micronaut.runtime.event.annotation.EventListener; -import jakarta.inject.Singleton; -import java.lang.invoke.MethodHandles; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * EventListeners registers event listeners for the startup and shutdown events from Micronaut. - */ -@Singleton -class EventListeners { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final List emitters; - private final ScheduledExecutorService executor; - - EventListeners(final List emitters) { - this.emitters = emitters; - this.executor = Executors.newScheduledThreadPool(emitters.size()); - } - - /** - * Manually registers all the emitters to run on startup. - * - * @param event unused but required in order to listen to the startup event. - */ - @EventListener - public void startEmitters(final ApplicationStartupEvent event) { - emitters.forEach(emitter -> executor.scheduleAtFixedRate(emitter::Emit, 0, emitter.getDuration().getSeconds(), TimeUnit.SECONDS)); - log.info("registered {} emitters", emitters.size()); - } - - /** - * Attempts to cleanly shutdown the running emitters - * - * @param event unused but required in order to listen to the shutdown event. - */ - @EventListener - public void stopEmitters(final ApplicationShutdownEvent event) { - log.info("shutting down emitters"); - executor.shutdown(); - } - -} diff --git a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/MetricRepository.java b/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/MetricRepository.java deleted file mode 100644 index 7fee4766a701f..0000000000000 --- a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/MetricRepository.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import static io.airbyte.db.instance.configs.jooq.generated.Tables.CONNECTION; -import static io.airbyte.db.instance.jobs.jooq.generated.Tables.ATTEMPTS; -import static io.airbyte.db.instance.jobs.jooq.generated.Tables.JOBS; -import static org.jooq.impl.DSL.asterisk; -import static org.jooq.impl.DSL.count; -import static org.jooq.impl.DSL.name; -import static org.jooq.impl.SQLDataType.VARCHAR; - -import io.airbyte.db.instance.configs.jooq.generated.enums.StatusType; -import io.airbyte.db.instance.jobs.jooq.generated.enums.AttemptStatus; -import io.airbyte.db.instance.jobs.jooq.generated.enums.JobStatus; -import jakarta.inject.Singleton; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.jooq.DSLContext; -import org.jooq.Field; -import org.jooq.impl.DSL; - -@Singleton -class MetricRepository { - - private final DSLContext ctx; - - // We have to report gauge metric with value 0 if they are not showing up in the DB, - // otherwise datadog will use previous reported value. - // Another option we didn't use here is to build this into SQL query - it will lead SQL much less - // readable while not decreasing any complexity. - private final static List REGISTERED_ATTEMPT_QUEUE = List.of("SYNC", "AWS_PARIS_SYNC", "null"); - private final static List REGISTERED_GEOGRAPHY = List.of("US", "AUTO", "EU"); - - MetricRepository(final DSLContext ctx) { - this.ctx = ctx; - } - - Map numberOfPendingJobsByGeography() { - String geographyResultAlias = "geography"; - String countResultAlias = "result"; - var result = ctx.select(CONNECTION.GEOGRAPHY.cast(String.class).as(geographyResultAlias), count(asterisk()).as(countResultAlias)) - .from(JOBS) - .join(CONNECTION) - .on(CONNECTION.ID.cast(VARCHAR(255)).eq(JOBS.SCOPE)) - .where(JOBS.STATUS.eq(JobStatus.pending)) - .groupBy(CONNECTION.GEOGRAPHY); - Field geographyResultField = DSL.field(name(geographyResultAlias), String.class); - Field countResultField = DSL.field(name(countResultAlias), Integer.class); - Map queriedMap = result.fetchMap(geographyResultField, countResultField); - for (final String potentialGeography : REGISTERED_GEOGRAPHY) { - if (!queriedMap.containsKey(potentialGeography)) { - queriedMap.put(potentialGeography, 0); - } - } - return queriedMap; - } - - Map numberOfRunningJobsByTaskQueue() { - String countFieldName = "count"; - var result = ctx.select(ATTEMPTS.PROCESSING_TASK_QUEUE, count(asterisk()).as(countFieldName)) - .from(JOBS) - .join(CONNECTION) - .on(CONNECTION.ID.cast(VARCHAR(255)).eq(JOBS.SCOPE)) - .join(ATTEMPTS) - .on(ATTEMPTS.JOB_ID.eq(JOBS.ID)) - .where(JOBS.STATUS.eq(JobStatus.running).and(CONNECTION.STATUS.eq(StatusType.active))) - .and(ATTEMPTS.STATUS.eq(AttemptStatus.running)) - .groupBy(ATTEMPTS.PROCESSING_TASK_QUEUE); - - Field countResultField = DSL.field(name(countFieldName), Integer.class); - Map queriedMap = result.fetchMap(ATTEMPTS.PROCESSING_TASK_QUEUE, countResultField); - for (final String potentialAttemptQueue : REGISTERED_ATTEMPT_QUEUE) { - if (!queriedMap.containsKey(potentialAttemptQueue)) { - queriedMap.put(potentialAttemptQueue, 0); - } - } - return queriedMap; - } - - // This is a rare case and not likely to be related to data planes; So we will monitor them as a - // whole. - int numberOfOrphanRunningJobs() { - return ctx.selectCount() - .from(JOBS) - .join(CONNECTION) - .on(CONNECTION.ID.cast(VARCHAR(255)).eq(JOBS.SCOPE)) - .where(JOBS.STATUS.eq(JobStatus.running).and(CONNECTION.STATUS.ne(StatusType.active))) - .fetchOne(0, int.class); - } - - Map oldestPendingJobAgeSecsByGeography() { - final var query = - """ - SELECT cast(connection.geography as varchar) AS geography, MAX(EXTRACT(EPOCH FROM (current_timestamp - jobs.created_at))) AS run_duration_seconds - FROM jobs - JOIN connection - ON jobs.scope::uuid = connection.id - WHERE jobs.status = 'pending' - GROUP BY geography; - """; - final var result = ctx.fetch(query); - Field geographyResultField = DSL.field(name("geography"), String.class); - Field runDurationSecondsField = DSL.field(name("run_duration_seconds"), Double.class); - Map queriedMap = result.intoMap(geographyResultField, runDurationSecondsField); - for (final String potentialGeography : REGISTERED_GEOGRAPHY) { - if (!queriedMap.containsKey(potentialGeography)) { - queriedMap.put(potentialGeography, 0.0); - } - } - return queriedMap; - } - - Map oldestRunningJobAgeSecsByTaskQueue() { - final var query = - """ - SELECT attempts.processing_task_queue AS task_queue, MAX(EXTRACT(EPOCH FROM (current_timestamp - jobs.created_at))) AS run_duration_seconds - FROM jobs - JOIN attempts - ON jobs.id = attempts.job_id - WHERE jobs.status = 'running' AND attempts.status = 'running' - GROUP BY task_queue; - """; - final var result = ctx.fetch(query); - Field taskQueueResultField = DSL.field(name("task_queue"), String.class); - Field runDurationSecondsField = DSL.field(name("run_duration_seconds"), Double.class); - Map queriedMap = result.intoMap(taskQueueResultField, runDurationSecondsField); - for (final String potentialAttemptQueue : REGISTERED_ATTEMPT_QUEUE) { - if (!queriedMap.containsKey(potentialAttemptQueue)) { - queriedMap.put(potentialAttemptQueue, 0.0); - } - } - return queriedMap; - } - - List numberOfActiveConnPerWorkspace() { - final var query = """ - SELECT workspace_id, count(c.id) as num_conn - FROM actor - INNER JOIN workspace ws ON actor.workspace_id = ws.id - INNER JOIN connection c ON actor.id = c.source_id - WHERE ws.tombstone = false - AND actor.tombstone = false AND actor.actor_type = 'source' - AND c.status = 'active' - GROUP BY workspace_id; - """; - return ctx.fetch(query).getValues("num_conn", long.class); - } - - long numScheduledActiveConnectionsInLastDay() { - final var queryForTotalConnections = """ - select count(1) as connection_count - from connection c - where - c.updated_at < now() - interval '24 hours 1 minutes' - and cast(c.schedule::jsonb->'timeUnit' as text) IN ('"hours"', '"minutes"') - and c.status = 'active' - """; - - return ctx.fetchOne(queryForTotalConnections).get("connection_count", long.class); - } - - long numberOfJobsNotRunningOnScheduleInLastDay() { - // This query finds all sync jobs ran in last 24 hours and count how many times they have run. - // Comparing this to the expected number of runs (24 hours divide by configured cadence in hours), - // if it runs below that expected number it will be considered as abnormal instance. - // For example, if it's configured to run every 6 hours but in last 24 hours it only has 3 runs, - // it will be considered as 1 abnormal instance. - final var queryForAbnormalSyncInHoursInLastDay = """ - select count(1) as cnt - from ( - select - c.id, - count(*) as cnt - from connection c - left join jobs j on j.scope::uuid = c.id - where - c.schedule is not null - and c.schedule != 'null' - and j.created_at > now() - interval '24 hours 1 minutes' - and c.status = 'active' - and j.config_type = 'sync' - and c.updated_at < now() - interval '24 hours 1 minutes' - and cast(c.schedule::jsonb->'timeUnit' as text) = '"hours"' - group by 1 - having count(*) < 24 / cast(c.schedule::jsonb->'units' as integer) - ) as abnormal_jobs - """; - - // Similar to the query above, this finds if the connection cadence's timeUnit is minutes. - // thus we use 1440 (=24 hours x 60 minutes) to divide the configured cadence. - final var queryForAbnormalSyncInMinutesInLastDay = """ - select count(1) as cnt - from ( - select - c.id, - count(*) as cnt - from - connection c - left join Jobs j on - j.scope::uuid = c.id - where - c.schedule is not null - and c.schedule != 'null' - and j.created_at > now() - interval '24 hours 1 minutes' - and c.status = 'active' - and j.config_type = 'sync' - and c.updated_at < now() - interval '24 hours 1 minutes' - and cast(c.schedule::jsonb->'timeUnit' as text) = '"minutes"' - group by 1 - having count(*) < 1440 / cast(c.schedule::jsonb->'units' as integer) - ) as abnormal_jobs - """; - return ctx.fetchOne(queryForAbnormalSyncInHoursInLastDay).get("cnt", long.class) - + ctx.fetchOne(queryForAbnormalSyncInMinutesInLastDay).get("cnt", long.class); - } - - long numberOfJobsRunningUnusuallyLong() { - // Definition of unusually long means runtime is more than 2x historic avg run time or 15 - // minutes more than avg run time, whichever is greater. - // It will skip jobs with fewer than 4 runs in last week to make sure the historic avg run is - // meaningful and consistent. - final var query = - """ - -- pick average running time and last sync running time in attempts table. - select - current_running_attempts.connection_id, - current_running_attempts.running_time, - historic_avg_running_attempts.avg_run_sec - from - ( - -- Sub-query-1: query the currently running attempt's running time. - ( - select - jobs.scope as connection_id, - extract(epoch from age(NOW(), attempts.created_at)) as running_time - from - jobs - join attempts on - jobs.id = attempts.job_id - where - jobs.status = 'running' - and attempts.status = 'running' - and jobs.config_type = 'sync' ) - as current_running_attempts - join - -- Sub-query-2: query historic attempts' average running time within last week. - ( - select - jobs.scope as connection_id, - avg(extract(epoch from age(attempts.updated_at, attempts.created_at))) as avg_run_sec - from - jobs - join attempts on - jobs.id = attempts.job_id - where - -- 168 hours is 1 week: we look for all attempts in last week to calculate its average running time. - attempts.updated_at >= NOW() - interval '168 HOUR' - and jobs.status = 'succeeded' - and attempts.status = 'succeeded' - and jobs.config_type = 'sync' - group by - connection_id - having - count(*) > 4 - ) as historic_avg_running_attempts - on - current_running_attempts.connection_id = historic_avg_running_attempts.connection_id) - where - -- Find if currently running time takes 2x more time than average running time, - -- and it's 15 minutes (900 seconds) more than average running time so it won't alert on noises for quick sync jobs. - current_running_attempts.running_time > greatest(historic_avg_running_attempts.avg_run_sec * 2, historic_avg_running_attempts.avg_run_sec + 900) - """; - final var queryResults = ctx.fetch(query); - return queryResults.getValues("connection_id").size(); - } - - Map overallJobRuntimeForTerminalJobsInLastHour() { - final var query = """ - SELECT status, extract(epoch from age(updated_at, created_at)) AS sec FROM jobs - WHERE updated_at >= NOW() - INTERVAL '1 HOUR' - AND jobs.status IN ('failed', 'succeeded', 'cancelled'); - """; - final var queryResults = ctx.fetch(query); - final var statuses = queryResults.getValues("status", JobStatus.class); - final var times = queryResults.getValues("sec", double.class); - - final var results = new HashMap(); - for (int i = 0; i < statuses.size(); i++) { - results.put(statuses.get(i), times.get(i)); - } - - return results; - } - -} diff --git a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/ReporterFactory.java b/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/ReporterFactory.java deleted file mode 100644 index 4e3c0e2413c00..0000000000000 --- a/airbyte-metrics/reporter/src/main/java/io/airbyte/metrics/reporter/ReporterFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import io.airbyte.metrics.lib.MetricClient; -import io.airbyte.metrics.lib.MetricClientFactory; -import io.micronaut.context.annotation.Factory; -import jakarta.inject.Singleton; - -/** - * Micronaut factory for creating the appropriate singletons utilized by the metric reporter - * service. - */ -@Factory -class ReporterFactory { - - @Singleton - public MetricClient metricClient() { - return MetricClientFactory.getMetricClient(); - } - -} diff --git a/airbyte-metrics/reporter/src/main/resources/application.yml b/airbyte-metrics/reporter/src/main/resources/application.yml deleted file mode 100644 index 49dd8cb8d7ae4..0000000000000 --- a/airbyte-metrics/reporter/src/main/resources/application.yml +++ /dev/null @@ -1,38 +0,0 @@ -micronaut: - application: - name: airbyte-metrics-reporter - security: - intercept-url-map: - - pattern: /** - httpMethod: GET - access: - - isAnonymous() - server: - port: 9000 - -datasources: - config: - connection-test-query: SELECT 1 - connection-timeout: 30000 - idle-timeout: 600000 - maximum-pool-size: 10 - url: ${DATABASE_URL} - driverClassName: org.postgresql.Driver - username: ${DATABASE_USER} - password: ${DATABASE_PASSWORD} - -jooq: - datasources: - config: - jackson-converter-enabled: true - sql-dialect: POSTGRES - -endpoints: - all: - enabled: true - -logger: - levels: - io.airbyte.bootloader: DEBUG -# Uncomment to help resolve issues with conditional beans -# io.micronaut.context.condition: DEBUG diff --git a/airbyte-metrics/reporter/src/main/resources/micronaut-banner.txt b/airbyte-metrics/reporter/src/main/resources/micronaut-banner.txt deleted file mode 100644 index 633f73326c1ab..0000000000000 --- a/airbyte-metrics/reporter/src/main/resources/micronaut-banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - - ___ _ __ __ - / | (_)____/ /_ __ __/ /____ - / /| | / / ___/ __ \/ / / / __/ _ \ - / ___ |/ / / / /_/ / /_/ / /_/ __/ -/_/ |_/_/_/ /_.___/\__, /\__/\___/ - /____/ - : airbyte-metrics-reporter : \ No newline at end of file diff --git a/airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/EmitterTest.java b/airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/EmitterTest.java deleted file mode 100644 index 2c0bb854166ae..0000000000000 --- a/airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/EmitterTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import io.airbyte.db.instance.jobs.jooq.generated.enums.JobStatus; -import io.airbyte.metrics.lib.MetricAttribute; -import io.airbyte.metrics.lib.MetricClient; -import io.airbyte.metrics.lib.MetricTags; -import io.airbyte.metrics.lib.OssMetricsRegistry; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class EmitterTest { - - private MetricClient client; - private MetricRepository repo; - - private static final String SYNC_QUEUE = "SYNC"; - private static final String AWS_QUEUE = "AWS"; - - private static final String EU_REGION = "EU"; - private static final String AUTO_REGION = "AUTO"; - - @BeforeEach - void setUp() { - client = mock(MetricClient.class); - repo = mock(MetricRepository.class); - } - - @Test - void TestNumPendingJobs() { - final var value = Map.of(AUTO_REGION, 101, EU_REGION, 20); - when(repo.numberOfPendingJobsByGeography()).thenReturn(value); - - final var emitter = new NumPendingJobs(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofSeconds(15), emitter.getDuration()); - verify(repo).numberOfPendingJobsByGeography(); - verify(client).gauge(OssMetricsRegistry.NUM_PENDING_JOBS, 101, - new MetricAttribute(MetricTags.GEOGRAPHY, AUTO_REGION)); - verify(client).gauge(OssMetricsRegistry.NUM_PENDING_JOBS, 20, - new MetricAttribute(MetricTags.GEOGRAPHY, EU_REGION)); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestNumRunningJobs() { - final var value = Map.of(SYNC_QUEUE, 101, AWS_QUEUE, 20); - when(repo.numberOfRunningJobsByTaskQueue()).thenReturn(value); - - final var emitter = new NumRunningJobs(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofSeconds(15), emitter.getDuration()); - verify(repo).numberOfRunningJobsByTaskQueue(); - verify(client).gauge(OssMetricsRegistry.NUM_RUNNING_JOBS, 101, - new MetricAttribute(MetricTags.ATTEMPT_QUEUE, SYNC_QUEUE)); - verify(client).gauge(OssMetricsRegistry.NUM_RUNNING_JOBS, 20, - new MetricAttribute(MetricTags.ATTEMPT_QUEUE, AWS_QUEUE)); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestNumOrphanRunningJobs() { - final var value = 101; - when(repo.numberOfOrphanRunningJobs()).thenReturn(value); - - final var emitter = new NumOrphanRunningJobs(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofSeconds(15), emitter.getDuration()); - verify(repo).numberOfOrphanRunningJobs(); - verify(client).gauge(OssMetricsRegistry.NUM_ORPHAN_RUNNING_JOBS, value); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestOldestRunningJob() { - final var value = Map.of(SYNC_QUEUE, 101.0, AWS_QUEUE, 20.0); - when(repo.oldestRunningJobAgeSecsByTaskQueue()).thenReturn(value); - - final var emitter = new OldestRunningJob(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofSeconds(15), emitter.getDuration()); - verify(repo).oldestRunningJobAgeSecsByTaskQueue(); - verify(client).gauge(OssMetricsRegistry.OLDEST_RUNNING_JOB_AGE_SECS, 101, - new MetricAttribute(MetricTags.ATTEMPT_QUEUE, SYNC_QUEUE)); - verify(client).gauge(OssMetricsRegistry.OLDEST_RUNNING_JOB_AGE_SECS, 20, - new MetricAttribute(MetricTags.ATTEMPT_QUEUE, AWS_QUEUE)); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestOldestPendingJob() { - final var value = Map.of(AUTO_REGION, 101.0, EU_REGION, 20.0); - when(repo.oldestPendingJobAgeSecsByGeography()).thenReturn(value); - - final var emitter = new OldestPendingJob(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofSeconds(15), emitter.getDuration()); - verify(repo).oldestPendingJobAgeSecsByGeography(); - verify(client).gauge(OssMetricsRegistry.OLDEST_PENDING_JOB_AGE_SECS, 101, - new MetricAttribute(MetricTags.GEOGRAPHY, AUTO_REGION)); - verify(client).gauge(OssMetricsRegistry.OLDEST_PENDING_JOB_AGE_SECS, 20, - new MetricAttribute(MetricTags.GEOGRAPHY, EU_REGION)); - - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestNumActiveConnectionsPerWorkspace() { - final var values = List.of(101L, 202L); - when(repo.numberOfActiveConnPerWorkspace()).thenReturn(values); - - final var emitter = new NumActiveConnectionsPerWorkspace(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofSeconds(15), emitter.getDuration()); - verify(repo).numberOfActiveConnPerWorkspace(); - for (final var value : values) { - verify(client).distribution(OssMetricsRegistry.NUM_ACTIVE_CONN_PER_WORKSPACE, value); - } - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestNumAbnormalScheduledSyncs() { - final var value = 101; - when(repo.numberOfJobsNotRunningOnScheduleInLastDay()).thenReturn((long) value); - - final var emitter = new NumAbnormalScheduledSyncs(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofHours(1), emitter.getDuration()); - verify(repo).numberOfJobsNotRunningOnScheduleInLastDay(); - verify(client).gauge(OssMetricsRegistry.NUM_ABNORMAL_SCHEDULED_SYNCS_IN_LAST_DAY, value); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestTotalScheduledSyncs() { - final var value = 101; - when(repo.numScheduledActiveConnectionsInLastDay()).thenReturn((long) value); - - final var emitter = new TotalScheduledSyncs(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofHours(1), emitter.getDuration()); - verify(repo).numScheduledActiveConnectionsInLastDay(); - verify(client).gauge(OssMetricsRegistry.NUM_TOTAL_SCHEDULED_SYNCS_IN_LAST_DAY, value); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - - @Test - void TestTotalJobRuntimeByTerminalState() { - final var values = Map.of(JobStatus.cancelled, 101.0, JobStatus.succeeded, 202.0, - JobStatus.failed, 303.0); - when(repo.overallJobRuntimeForTerminalJobsInLastHour()).thenReturn(values); - - final var emitter = new TotalJobRuntimeByTerminalState(client, repo); - emitter.Emit(); - - assertEquals(Duration.ofHours(1), emitter.getDuration()); - verify(repo).overallJobRuntimeForTerminalJobsInLastHour(); - values.forEach((jobStatus, time) -> { - verify(client).distribution( - OssMetricsRegistry.OVERALL_JOB_RUNTIME_IN_LAST_HOUR_BY_TERMINAL_STATE_SECS, time, - new MetricAttribute(MetricTags.JOB_STATUS, jobStatus.getLiteral())); - }); - verify(client).count(OssMetricsRegistry.EST_NUM_METRICS_EMITTED_BY_REPORTER, 1); - } - -} diff --git a/airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/MetricRepositoryTest.java b/airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/MetricRepositoryTest.java deleted file mode 100644 index 85dee029d5a27..0000000000000 --- a/airbyte-metrics/reporter/src/test/java/io/airbyte/metrics/reporter/MetricRepositoryTest.java +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.metrics.reporter; - -import static io.airbyte.db.instance.configs.jooq.generated.Keys.ACTOR_CATALOG_FETCH_EVENT__ACTOR_CATALOG_FETCH_EVENT_ACTOR_ID_FKEY; -import static io.airbyte.db.instance.configs.jooq.generated.Keys.ACTOR__ACTOR_WORKSPACE_ID_FKEY; -import static io.airbyte.db.instance.configs.jooq.generated.Keys.CONNECTION__CONNECTION_DESTINATION_ID_FKEY; -import static io.airbyte.db.instance.configs.jooq.generated.Keys.CONNECTION__CONNECTION_SOURCE_ID_FKEY; -import static io.airbyte.db.instance.configs.jooq.generated.Tables.ACTOR; -import static io.airbyte.db.instance.configs.jooq.generated.Tables.ACTOR_CATALOG_FETCH_EVENT; -import static io.airbyte.db.instance.configs.jooq.generated.Tables.ACTOR_DEFINITION; -import static io.airbyte.db.instance.configs.jooq.generated.Tables.CONNECTION; -import static io.airbyte.db.instance.configs.jooq.generated.Tables.WORKSPACE; -import static io.airbyte.db.instance.jobs.jooq.generated.Tables.ATTEMPTS; -import static io.airbyte.db.instance.jobs.jooq.generated.Tables.JOBS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.airbyte.db.factory.DSLContextFactory; -import io.airbyte.db.init.DatabaseInitializationException; -import io.airbyte.db.instance.configs.jooq.generated.enums.ActorType; -import io.airbyte.db.instance.configs.jooq.generated.enums.GeographyType; -import io.airbyte.db.instance.configs.jooq.generated.enums.NamespaceDefinitionType; -import io.airbyte.db.instance.configs.jooq.generated.enums.ReleaseStage; -import io.airbyte.db.instance.configs.jooq.generated.enums.StatusType; -import io.airbyte.db.instance.jobs.jooq.generated.enums.AttemptStatus; -import io.airbyte.db.instance.jobs.jooq.generated.enums.JobConfigType; -import io.airbyte.db.instance.jobs.jooq.generated.enums.JobStatus; -import io.airbyte.db.instance.test.TestDatabaseProviders; -import io.airbyte.test.utils.DatabaseConnectionHelper; -import java.io.IOException; -import java.sql.SQLException; -import java.time.OffsetDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Map; -import java.util.UUID; -import org.jooq.DSLContext; -import org.jooq.JSONB; -import org.jooq.SQLDialect; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.testcontainers.containers.PostgreSQLContainer; - -class MetricRepositoryTest { - - private static final String SRC = "src"; - private static final String DEST = "dst"; - private static final String CONN = "conn"; - private static final String SYNC_QUEUE = "SYNC"; - private static final String AWS_SYNC_QUEUE = "AWS_PARIS_SYNC"; - private static final String AUTO_REGION = "AUTO"; - private static final String EU_REGION = "EU"; - - private static final UUID SRC_DEF_ID = UUID.randomUUID(); - private static final UUID DST_DEF_ID = UUID.randomUUID(); - private static MetricRepository db; - private static DSLContext ctx; - - @BeforeAll - public static void setUpAll() throws DatabaseInitializationException, IOException { - final var psqlContainer = new PostgreSQLContainer<>("postgres:13-alpine") - .withUsername("user") - .withPassword("hunter2"); - psqlContainer.start(); - - final var dataSource = DatabaseConnectionHelper.createDataSource(psqlContainer); - ctx = DSLContextFactory.create(dataSource, SQLDialect.POSTGRES); - final var dbProviders = new TestDatabaseProviders(dataSource, ctx); - dbProviders.createNewConfigsDatabase(); - dbProviders.createNewJobsDatabase(); - - ctx.insertInto(ACTOR_DEFINITION, ACTOR_DEFINITION.ID, ACTOR_DEFINITION.NAME, ACTOR_DEFINITION.DOCKER_REPOSITORY, - ACTOR_DEFINITION.DOCKER_IMAGE_TAG, ACTOR_DEFINITION.SPEC, ACTOR_DEFINITION.ACTOR_TYPE, ACTOR_DEFINITION.RELEASE_STAGE) - .values(SRC_DEF_ID, "srcDef", "repository", "tag", JSONB.valueOf("{}"), ActorType.source, ReleaseStage.beta) - .values(DST_DEF_ID, "dstDef", "repository", "tag", JSONB.valueOf("{}"), ActorType.destination, ReleaseStage.generally_available) - .values(UUID.randomUUID(), "dstDef", "repository", "tag", JSONB.valueOf("{}"), ActorType.destination, ReleaseStage.alpha) - .execute(); - - // drop constraints to simplify test set up - ctx.alterTable(ACTOR).dropForeignKey(ACTOR__ACTOR_WORKSPACE_ID_FKEY.constraint()).execute(); - ctx.alterTable(CONNECTION).dropForeignKey(CONNECTION__CONNECTION_DESTINATION_ID_FKEY.constraint()).execute(); - ctx.alterTable(CONNECTION).dropForeignKey(CONNECTION__CONNECTION_SOURCE_ID_FKEY.constraint()).execute(); - ctx.alterTable(ACTOR_CATALOG_FETCH_EVENT) - .dropForeignKey(ACTOR_CATALOG_FETCH_EVENT__ACTOR_CATALOG_FETCH_EVENT_ACTOR_ID_FKEY.constraint()).execute(); - ctx.alterTable(WORKSPACE).alter(WORKSPACE.SLUG).dropNotNull().execute(); - ctx.alterTable(WORKSPACE).alter(WORKSPACE.INITIAL_SETUP_COMPLETE).dropNotNull().execute(); - - db = new MetricRepository(ctx); - } - - @BeforeEach - void setUp() { - ctx.truncate(ACTOR).execute(); - ctx.truncate(CONNECTION).cascade().execute(); - ctx.truncate(JOBS).cascade().execute(); - ctx.truncate(ATTEMPTS).cascade().execute(); - ctx.truncate(WORKSPACE).cascade().execute(); - } - - @AfterEach - void tearDown() { - - } - - @Nested - class NumJobs { - - @Test - void shouldReturnReleaseStages() { - ctx.insertInto(ATTEMPTS, ATTEMPTS.ID, ATTEMPTS.JOB_ID, ATTEMPTS.STATUS, ATTEMPTS.PROCESSING_TASK_QUEUE) - .values(10L, 1L, AttemptStatus.running, SYNC_QUEUE).values(20L, 2L, AttemptStatus.running, SYNC_QUEUE) - .values(30L, 3L, AttemptStatus.running, SYNC_QUEUE).values(40L, 4L, AttemptStatus.running, AWS_SYNC_QUEUE) - .values(50L, 5L, AttemptStatus.running, SYNC_QUEUE) - .execute(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - final var activeConnectionId = UUID.randomUUID(); - final var inactiveConnectionId = UUID.randomUUID(); - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.STATUS, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, - CONNECTION.DESTINATION_ID, CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL) - .values(activeConnectionId, StatusType.active, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true) - .values(inactiveConnectionId, StatusType.inactive, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true) - .execute(); - - // non-pending jobs - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(1L, activeConnectionId.toString(), JobStatus.pending) - .execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(2L, activeConnectionId.toString(), JobStatus.failed) - .values(3L, activeConnectionId.toString(), JobStatus.running) - .values(4L, activeConnectionId.toString(), JobStatus.running) - .values(5L, inactiveConnectionId.toString(), JobStatus.running) - .execute(); - - assertEquals(1, db.numberOfRunningJobsByTaskQueue().get(SYNC_QUEUE)); - assertEquals(1, db.numberOfRunningJobsByTaskQueue().get(AWS_SYNC_QUEUE)); - // To test we send 0 for 'null' to overwrite previous bug. - assertEquals(0, db.numberOfRunningJobsByTaskQueue().get("null")); - assertEquals(1, db.numberOfOrphanRunningJobs()); - } - - @Test - void runningJobsShouldReturnZero() throws SQLException { - // non-pending jobs - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS).values(1L, "", JobStatus.pending).execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS).values(2L, "", JobStatus.failed).execute(); - - final var result = db.numberOfRunningJobsByTaskQueue(); - assertEquals(result.get(SYNC_QUEUE), 0); - assertEquals(result.get(AWS_SYNC_QUEUE), 0); - } - - @Test - void pendingJobsShouldReturnCorrectCount() throws SQLException { - // non-pending jobs - final var connectionUuid = UUID.randomUUID(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS, CONNECTION.GEOGRAPHY) - .values(connectionUuid, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active, - GeographyType.valueOf(EU_REGION)) - .execute(); - - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(1L, connectionUuid.toString(), JobStatus.pending) - .values(2L, connectionUuid.toString(), JobStatus.failed) - .values(3L, connectionUuid.toString(), JobStatus.pending) - .values(4L, connectionUuid.toString(), JobStatus.running) - .execute(); - - final var res = db.numberOfPendingJobsByGeography(); - assertEquals(2, res.get(EU_REGION)); - assertEquals(0, res.get(AUTO_REGION)); - } - - @Test - void pendingJobsShouldReturnZero() throws SQLException { - final var connectionUuid = UUID.randomUUID(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS, CONNECTION.GEOGRAPHY) - .values(connectionUuid, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active, - GeographyType.valueOf(EU_REGION)) - .execute(); - - // non-pending jobs - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(1L, connectionUuid.toString(), JobStatus.running) - .values(2L, connectionUuid.toString(), JobStatus.failed) - .execute(); - - final var result = db.numberOfPendingJobsByGeography(); - assertEquals(result.get(AUTO_REGION), 0); - assertEquals(result.get(EU_REGION), 0); - } - - } - - @Nested - class OldestPendingJob { - - @Test - void shouldReturnOnlyPendingSeconds() throws SQLException { - final var expAgeSecs = 1000; - final var oldestCreateAt = OffsetDateTime.now().minus(expAgeSecs, ChronoUnit.SECONDS); - final var connectionUuid = UUID.randomUUID(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS, CONNECTION.GEOGRAPHY) - .values(connectionUuid, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active, - GeographyType.valueOf(EU_REGION)) - .execute(); - - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT) - // oldest pending job - .values(1L, connectionUuid.toString(), JobStatus.pending, oldestCreateAt) - // second-oldest pending job - .values(2L, connectionUuid.toString(), JobStatus.pending, OffsetDateTime.now()) - .execute(); - // non-pending jobs - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(3L, connectionUuid.toString(), JobStatus.running) - .values(4L, connectionUuid.toString(), JobStatus.failed) - .execute(); - - Double result = db.oldestPendingJobAgeSecsByGeography().get(EU_REGION); - // expected age is 1000 seconds, but allow for +/- 1 second to account for timing/rounding errors - assertTrue(999 < result && result < 1001); - } - - @Test - void shouldReturnNothingIfNotApplicable() { - final var connectionUuid = UUID.randomUUID(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS, CONNECTION.GEOGRAPHY) - .values(connectionUuid, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active, GeographyType.EU) - .execute(); - - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(1L, connectionUuid.toString(), JobStatus.succeeded) - .values(2L, connectionUuid.toString(), JobStatus.running) - .values(3L, connectionUuid.toString(), JobStatus.failed).execute(); - - final var result = db.oldestPendingJobAgeSecsByGeography(); - assertEquals(result.get(EU_REGION), 0.0); - assertEquals(result.get(AUTO_REGION), 0.0); - } - - } - - @Nested - class OldestRunningJob { - - @Test - void shouldReturnOnlyRunningSeconds() { - final var expAgeSecs = 10000; - final var oldestCreateAt = OffsetDateTime.now().minus(expAgeSecs, ChronoUnit.SECONDS); - ctx.insertInto(ATTEMPTS, ATTEMPTS.ID, ATTEMPTS.JOB_ID, ATTEMPTS.STATUS, ATTEMPTS.PROCESSING_TASK_QUEUE) - .values(10L, 1L, AttemptStatus.running, SYNC_QUEUE).values(20L, 2L, AttemptStatus.running, SYNC_QUEUE) - .execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT) - // oldest pending job - .values(1L, "", JobStatus.running, oldestCreateAt) - // second-oldest pending job - .values(2L, "", JobStatus.running, OffsetDateTime.now()) - .execute(); - - // non-pending jobs - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(3L, "", JobStatus.pending) - .values(4L, "", JobStatus.failed) - .execute(); - - final var result = db.oldestRunningJobAgeSecsByTaskQueue(); - // expected age is 1000 seconds, but allow for +/- 1 second to account for timing/rounding errors - assertTrue(9999 < result.get(SYNC_QUEUE) && result.get(SYNC_QUEUE) < 10001L); - assertEquals(result.get(AWS_SYNC_QUEUE), 0.0); - } - - @Test - void shouldReturnNothingIfNotApplicable() { - ctx.insertInto(ATTEMPTS, ATTEMPTS.ID, ATTEMPTS.JOB_ID, ATTEMPTS.PROCESSING_TASK_QUEUE).values(10L, 1L, SYNC_QUEUE).values(20L, 2L, SYNC_QUEUE) - .values(30L, 3L, SYNC_QUEUE).execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(1L, "", JobStatus.succeeded) - .values(2L, "", JobStatus.pending) - .values(3L, "", JobStatus.failed) - .execute(); - - final var result = db.oldestRunningJobAgeSecsByTaskQueue(); - assertEquals(result.get(SYNC_QUEUE), 0.0); - assertEquals(result.get(AWS_SYNC_QUEUE), 0.0); - } - - } - - @Nested - class NumActiveConnsPerWorkspace { - - @Test - void shouldReturnNumConnectionsBasic() { - final var workspaceId = UUID.randomUUID(); - ctx.insertInto(WORKSPACE, WORKSPACE.ID, WORKSPACE.NAME, WORKSPACE.TOMBSTONE) - .values(workspaceId, "test-0", false) - .execute(); - - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - ctx.insertInto(ACTOR, ACTOR.ID, ACTOR.WORKSPACE_ID, ACTOR.ACTOR_DEFINITION_ID, ACTOR.NAME, ACTOR.CONFIGURATION, ACTOR.ACTOR_TYPE, - ACTOR.TOMBSTONE) - .values(srcId, workspaceId, SRC_DEF_ID, SRC, JSONB.valueOf("{}"), ActorType.source, false) - .values(dstId, workspaceId, DST_DEF_ID, DEST, JSONB.valueOf("{}"), ActorType.destination, false) - .execute(); - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active) - .execute(); - - final var res = db.numberOfActiveConnPerWorkspace(); - assertEquals(1, res.size()); - assertEquals(2, res.get(0)); - } - - @Test - @DisplayName("should ignore deleted connections") - void shouldIgnoreNonRunningConnections() { - final var workspaceId = UUID.randomUUID(); - ctx.insertInto(WORKSPACE, WORKSPACE.ID, WORKSPACE.NAME, WORKSPACE.TOMBSTONE) - .values(workspaceId, "test-0", false) - .execute(); - - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - ctx.insertInto(ACTOR, ACTOR.ID, ACTOR.WORKSPACE_ID, ACTOR.ACTOR_DEFINITION_ID, ACTOR.NAME, ACTOR.CONFIGURATION, ACTOR.ACTOR_TYPE, - ACTOR.TOMBSTONE) - .values(srcId, workspaceId, SRC_DEF_ID, SRC, JSONB.valueOf("{}"), ActorType.source, false) - .values(dstId, workspaceId, DST_DEF_ID, DEST, JSONB.valueOf("{}"), ActorType.destination, false) - .execute(); - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.deprecated) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.inactive) - .execute(); - - final var res = db.numberOfActiveConnPerWorkspace(); - assertEquals(1, res.size()); - assertEquals(2, res.get(0)); - } - - @Test - @DisplayName("should ignore deleted connections") - void shouldIgnoreDeletedWorkspaces() { - final var workspaceId = UUID.randomUUID(); - ctx.insertInto(WORKSPACE, WORKSPACE.ID, WORKSPACE.NAME, WORKSPACE.TOMBSTONE) - .values(workspaceId, "test-0", true) - .execute(); - - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - ctx.insertInto(ACTOR, ACTOR.ID, ACTOR.WORKSPACE_ID, ACTOR.ACTOR_DEFINITION_ID, ACTOR.NAME, ACTOR.CONFIGURATION, ACTOR.ACTOR_TYPE, - ACTOR.TOMBSTONE) - .values(srcId, workspaceId, SRC_DEF_ID, SRC, JSONB.valueOf("{}"), ActorType.source, false) - .values(dstId, workspaceId, DST_DEF_ID, DEST, JSONB.valueOf("{}"), ActorType.destination, false) - .execute(); - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.MANUAL, CONNECTION.STATUS) - .values(UUID.randomUUID(), NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), true, StatusType.active) - .execute(); - - final var res = db.numberOfActiveConnPerWorkspace(); - assertEquals(0, res.size()); - } - - @Test - void shouldReturnNothingIfNotApplicable() { - final var res = db.numberOfActiveConnPerWorkspace(); - assertEquals(0, res.size()); - } - - } - - @Nested - class OverallJobRuntimeForTerminalJobsInLastHour { - - @Test - void shouldIgnoreNonTerminalJobs() throws SQLException { - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS) - .values(1L, "", JobStatus.running) - .values(2L, "", JobStatus.incomplete) - .values(3L, "", JobStatus.pending) - .execute(); - - final var res = db.overallJobRuntimeForTerminalJobsInLastHour(); - assertEquals(0, res.size()); - } - - @Test - void shouldIgnoreJobsOlderThan1Hour() { - final var updateAt = OffsetDateTime.now().minus(2, ChronoUnit.HOURS); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.UPDATED_AT).values(1L, "", JobStatus.succeeded, updateAt).execute(); - - final var res = db.overallJobRuntimeForTerminalJobsInLastHour(); - assertEquals(0, res.size()); - } - - @Test - @DisplayName("should return correct duration for terminal jobs") - void shouldReturnTerminalJobs() { - final var updateAt = OffsetDateTime.now(); - final var expAgeSecs = 10000; - final var createAt = updateAt.minus(expAgeSecs, ChronoUnit.SECONDS); - - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT) - .values(1L, "", JobStatus.succeeded, createAt, updateAt) - .execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT) - .values(2L, "", JobStatus.failed, createAt, updateAt) - .execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT) - .values(3L, "", JobStatus.cancelled, createAt, updateAt) - .execute(); - - final var res = db.overallJobRuntimeForTerminalJobsInLastHour(); - assertEquals(3, res.size()); - - final var exp = Map.of( - JobStatus.succeeded, expAgeSecs * 1.0, - JobStatus.cancelled, expAgeSecs * 1.0, - JobStatus.failed, expAgeSecs * 1.0); - assertEquals(exp, res); - } - - @Test - void shouldReturnTerminalJobsComplex() { - final var updateAtNow = OffsetDateTime.now(); - final var expAgeSecs = 10000; - final var createAt = updateAtNow.minus(expAgeSecs, ChronoUnit.SECONDS); - - // terminal jobs in last hour - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT) - .values(1L, "", JobStatus.succeeded, createAt, updateAtNow) - .execute(); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT) - .values(2L, "", JobStatus.failed, createAt, updateAtNow) - .execute(); - - // old terminal jobs - final var updateAtOld = OffsetDateTime.now().minus(2, ChronoUnit.HOURS); - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT) - .values(3L, "", JobStatus.cancelled, createAt, updateAtOld) - .execute(); - - // non-terminal jobs - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT) - .values(4L, "", JobStatus.running, createAt) - .execute(); - - final var res = db.overallJobRuntimeForTerminalJobsInLastHour(); - assertEquals(2, res.size()); - - final var exp = Map.of( - JobStatus.succeeded, expAgeSecs * 1.0, - JobStatus.failed, expAgeSecs * 1.0); - assertEquals(exp, res); - } - - @Test - void shouldReturnNothingIfNotApplicable() { - final var res = db.overallJobRuntimeForTerminalJobsInLastHour(); - assertEquals(0, res.size()); - } - - } - - @Nested - class AbnormalJobsInLastDay { - - @Test - void shouldCountInJobsWithMissingRun() throws SQLException { - final var updateAt = OffsetDateTime.now().minus(300, ChronoUnit.HOURS); - final var connectionId = UUID.randomUUID(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - final var syncConfigType = JobConfigType.sync; - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.SCHEDULE, CONNECTION.MANUAL, CONNECTION.STATUS, CONNECTION.CREATED_AT, - CONNECTION.UPDATED_AT) - .values(connectionId, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), - JSONB.valueOf("{\"units\": 6, \"timeUnit\": \"hours\"}"), false, StatusType.active, updateAt, updateAt) - .execute(); - - // Jobs running in prior day will not be counted - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT, JOBS.CONFIG_TYPE) - .values(100L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.HOURS), updateAt, syncConfigType) - .values(1L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.HOURS), updateAt, syncConfigType) - .values(2L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(10, ChronoUnit.HOURS), updateAt, syncConfigType) - .values(3L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(5, ChronoUnit.HOURS), updateAt, syncConfigType) - .execute(); - - final var totalConnectionResult = db.numScheduledActiveConnectionsInLastDay(); - assertEquals(1, totalConnectionResult); - - final var abnormalConnectionResult = db.numberOfJobsNotRunningOnScheduleInLastDay(); - assertEquals(1, abnormalConnectionResult); - } - - @Test - void shouldNotCountNormalJobsInAbnormalMetric() { - final var updateAt = OffsetDateTime.now().minus(300, ChronoUnit.HOURS); - final var inactiveConnectionId = UUID.randomUUID(); - final var activeConnectionId = UUID.randomUUID(); - final var srcId = UUID.randomUUID(); - final var dstId = UUID.randomUUID(); - final var syncConfigType = JobConfigType.sync; - - ctx.insertInto(CONNECTION, CONNECTION.ID, CONNECTION.NAMESPACE_DEFINITION, CONNECTION.SOURCE_ID, CONNECTION.DESTINATION_ID, - CONNECTION.NAME, CONNECTION.CATALOG, CONNECTION.SCHEDULE, CONNECTION.MANUAL, CONNECTION.STATUS, CONNECTION.CREATED_AT, - CONNECTION.UPDATED_AT) - .values(inactiveConnectionId, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), - JSONB.valueOf("{\"units\": 12, \"timeUnit\": \"hours\"}"), false, StatusType.inactive, updateAt, updateAt) - .values(activeConnectionId, NamespaceDefinitionType.source, srcId, dstId, CONN, JSONB.valueOf("{}"), - JSONB.valueOf("{\"units\": 12, \"timeUnit\": \"hours\"}"), false, StatusType.active, updateAt, updateAt) - .execute(); - - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT, JOBS.CONFIG_TYPE) - .values(1L, activeConnectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.HOURS), updateAt, - syncConfigType) - .values(2L, activeConnectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(10, ChronoUnit.HOURS), updateAt, - syncConfigType) - .execute(); - - final var totalConnectionResult = db.numScheduledActiveConnectionsInLastDay(); - assertEquals(1, totalConnectionResult); - - final var abnormalConnectionResult = db.numberOfJobsNotRunningOnScheduleInLastDay(); - assertEquals(0, abnormalConnectionResult); - } - - } - - @Nested - class UnusuallyLongJobs { - - @Test - void shouldCountInJobsWithUnusuallyLongTime() throws SQLException { - final var connectionId = UUID.randomUUID(); - final var syncConfigType = JobConfigType.sync; - - // Current job has been running for 12 hours while the previous 5 jobs runs 2 hours. Avg will be 2 - // hours. - // Thus latest job will be counted as an unusually long-running job. - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT, JOBS.CONFIG_TYPE) - .values(100L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.HOURS), - OffsetDateTime.now().minus(26, ChronoUnit.HOURS), syncConfigType) - .values(1L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.HOURS), - OffsetDateTime.now().minus(18, ChronoUnit.HOURS), syncConfigType) - .values(2L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(18, ChronoUnit.HOURS), - OffsetDateTime.now().minus(16, ChronoUnit.HOURS), syncConfigType) - .values(3L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(16, ChronoUnit.HOURS), - OffsetDateTime.now().minus(14, ChronoUnit.HOURS), syncConfigType) - .values(4L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(14, ChronoUnit.HOURS), - OffsetDateTime.now().minus(12, ChronoUnit.HOURS), syncConfigType) - .values(5L, connectionId.toString(), JobStatus.running, OffsetDateTime.now().minus(12, ChronoUnit.HOURS), - OffsetDateTime.now().minus(12, ChronoUnit.HOURS), syncConfigType) - .execute(); - - ctx.insertInto(ATTEMPTS, ATTEMPTS.ID, ATTEMPTS.JOB_ID, ATTEMPTS.STATUS, ATTEMPTS.CREATED_AT, ATTEMPTS.UPDATED_AT) - .values(100L, 100L, AttemptStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.HOURS), - OffsetDateTime.now().minus(26, ChronoUnit.HOURS)) - .values(1L, 1L, AttemptStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.HOURS), - OffsetDateTime.now().minus(18, ChronoUnit.HOURS)) - .values(2L, 2L, AttemptStatus.succeeded, OffsetDateTime.now().minus(18, ChronoUnit.HOURS), - OffsetDateTime.now().minus(16, ChronoUnit.HOURS)) - .values(3L, 3L, AttemptStatus.succeeded, OffsetDateTime.now().minus(16, ChronoUnit.HOURS), - OffsetDateTime.now().minus(14, ChronoUnit.HOURS)) - .values(4L, 4L, AttemptStatus.succeeded, OffsetDateTime.now().minus(14, ChronoUnit.HOURS), - OffsetDateTime.now().minus(12, ChronoUnit.HOURS)) - .values(5L, 5L, AttemptStatus.running, OffsetDateTime.now().minus(12, ChronoUnit.HOURS), - OffsetDateTime.now().minus(12, ChronoUnit.HOURS)) - .execute(); - - final var numOfJubsRunningUnusallyLong = db.numberOfJobsRunningUnusuallyLong(); - assertEquals(1, numOfJubsRunningUnusallyLong); - } - - @Test - void shouldNotCountInJobsWithinFifteenMinutes() throws SQLException { - final var connectionId = UUID.randomUUID(); - final var syncConfigType = JobConfigType.sync; - - // Latest job runs 14 minutes while the previous 5 jobs runs average about 3 minutes. - // Despite it has been more than 2x than avg it's still within 15 minutes threshold, thus this - // shouldn't be - // counted in. - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT, JOBS.CONFIG_TYPE) - .values(100L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(26, ChronoUnit.MINUTES), syncConfigType) - .values(1L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(18, ChronoUnit.MINUTES), syncConfigType) - .values(2L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(18, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(16, ChronoUnit.MINUTES), syncConfigType) - .values(3L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(16, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(14, ChronoUnit.MINUTES), syncConfigType) - .values(4L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(14, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(2, ChronoUnit.MINUTES), syncConfigType) - .values(5L, connectionId.toString(), JobStatus.running, OffsetDateTime.now().minus(14, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(2, ChronoUnit.MINUTES), syncConfigType) - .execute(); - - ctx.insertInto(ATTEMPTS, ATTEMPTS.ID, ATTEMPTS.JOB_ID, ATTEMPTS.STATUS, ATTEMPTS.CREATED_AT, ATTEMPTS.UPDATED_AT) - .values(100L, 100L, AttemptStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(26, ChronoUnit.MINUTES)) - .values(1L, 1L, AttemptStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(18, ChronoUnit.MINUTES)) - .values(2L, 2L, AttemptStatus.succeeded, OffsetDateTime.now().minus(18, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(16, ChronoUnit.MINUTES)) - .values(3L, 3L, AttemptStatus.succeeded, OffsetDateTime.now().minus(26, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(14, ChronoUnit.MINUTES)) - .values(4L, 4L, AttemptStatus.succeeded, OffsetDateTime.now().minus(18, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(17, ChronoUnit.MINUTES)) - .values(5L, 5L, AttemptStatus.running, OffsetDateTime.now().minus(14, ChronoUnit.MINUTES), - OffsetDateTime.now().minus(14, ChronoUnit.MINUTES)) - .execute(); - - final var numOfJubsRunningUnusallyLong = db.numberOfJobsRunningUnusuallyLong(); - assertEquals(0, numOfJubsRunningUnusallyLong); - } - - @Test - void shouldSkipInsufficientJobRuns() throws SQLException { - final var connectionId = UUID.randomUUID(); - final var syncConfigType = JobConfigType.sync; - - // Require at least 5 runs in last week to get meaningful average runtime. - ctx.insertInto(JOBS, JOBS.ID, JOBS.SCOPE, JOBS.STATUS, JOBS.CREATED_AT, JOBS.UPDATED_AT, JOBS.CONFIG_TYPE) - .values(100L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.HOURS), - OffsetDateTime.now().minus(26, ChronoUnit.HOURS), syncConfigType) - .values(1L, connectionId.toString(), JobStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.HOURS), - OffsetDateTime.now().minus(18, ChronoUnit.HOURS), syncConfigType) - .values(2L, connectionId.toString(), JobStatus.running, OffsetDateTime.now().minus(18, ChronoUnit.HOURS), - OffsetDateTime.now().minus(1, ChronoUnit.HOURS), syncConfigType) - .execute(); - - ctx.insertInto(ATTEMPTS, ATTEMPTS.ID, ATTEMPTS.JOB_ID, ATTEMPTS.STATUS, ATTEMPTS.CREATED_AT, ATTEMPTS.UPDATED_AT) - .values(100L, 100L, AttemptStatus.succeeded, OffsetDateTime.now().minus(28, ChronoUnit.HOURS), - OffsetDateTime.now().minus(26, ChronoUnit.HOURS)) - .values(1L, 1L, AttemptStatus.succeeded, OffsetDateTime.now().minus(20, ChronoUnit.HOURS), - OffsetDateTime.now().minus(18, ChronoUnit.HOURS)) - .values(2L, 2L, AttemptStatus.running, OffsetDateTime.now().minus(18, ChronoUnit.HOURS), - OffsetDateTime.now().minus(1, ChronoUnit.HOURS)) - .execute(); - - final var numOfJubsRunningUnusallyLong = db.numberOfJobsRunningUnusuallyLong(); - assertEquals(0, numOfJubsRunningUnusallyLong); - } - - } - -} diff --git a/airbyte-proxy/401.html b/airbyte-proxy/401.html deleted file mode 100644 index 69e19668f51b2..0000000000000 --- a/airbyte-proxy/401.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - Airbyte - Access Denied - - -

🐙 Nope.

-

HTTP Error Code: 401

- -

- This deployment of Airbyte is protected by HTTP Basic Authentication. - Please refer to the Airbyte docs to learn more about: -

-

- - diff --git a/airbyte-proxy/Dockerfile b/airbyte-proxy/Dockerfile deleted file mode 100644 index 3a8608f72c914..0000000000000 --- a/airbyte-proxy/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -# Inspired by https://medium.com/pernod-ricard-tech/adding-basic-authentication-with-nginx-as-a-reverse-proxy-a229f9d12b73 - -FROM nginx:latest - -ARG VERSION=0.40.32 - -ENV APPLICATION airbyte-proxy -ENV VERSION ${VERSION} - -RUN apt-get update -y && apt-get install -y apache2-utils && rm -rf /var/lib/apt/lists/* - -# This variable can be used to update the destination containers that Nginx proxies to. -ENV PROXY_PASS_WEB "http://airbyte-webapp:80" -ENV PROXY_PASS_API "http://airbyte-server:8001" -ENV CONNECTOR_BUILDER_SERVER_API "http://airbyte-connector-builder-server:80" - -# Nginx config file -WORKDIR / -RUN mkdir -p /etc/nginx/templates -COPY nginx-auth.conf.template /etc/nginx/templates/nginx-auth.conf.template -COPY nginx-no-auth.conf.template /etc/nginx/templates/nginx-no-auth.conf.template -COPY 401.html /etc/nginx/401.html - -# Startup script -COPY run.sh ./ -RUN chmod 0755 ./run.sh -CMD [ "./run.sh" ] -ENTRYPOINT ["./run.sh"] diff --git a/airbyte-proxy/LICENSE b/airbyte-proxy/LICENSE deleted file mode 100644 index 7d1808d83342e..0000000000000 --- a/airbyte-proxy/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Airbyte, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/airbyte-proxy/README.md b/airbyte-proxy/README.md deleted file mode 100644 index 1bb4f873fb37b..0000000000000 --- a/airbyte-proxy/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Airbyte Proxy - -This service uses Nginx to front the Aribyte `webapp` and `server` services to add Authentication via HTTP basic auth. - -Authentication is controlled by 2 environment variables, `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` which can be modified in the `.env` file for your Airbyte deployment. You can disable authentication by setting both `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` to empty strings. Changes in your environment variables will be applied when the service (re)boots. - -This service is intended to work in conjunction with the `airbyte_internal` network defined in the default docker compose file. By default, this application forwards requesting coming in on 8000 and 8001 to the PROXY_PASS_WEB and PROXY_PASS_API accordingly - which are also configured by environment variables within this container (see Dockerfile). The deafults are configured to work with the default `docker-compose.yaml` file for Airbyte OSS deployments. - -``` -ENV PROXY_PASS_WEB "http://airbyte-webapp:80" -ENV PROXY_PASS_API "http://airbyte-server:8001" -``` - -🐙 diff --git a/airbyte-proxy/build.gradle b/airbyte-proxy/build.gradle deleted file mode 100644 index 297f75c8f4c43..0000000000000 --- a/airbyte-proxy/build.gradle +++ /dev/null @@ -1,21 +0,0 @@ -task prepareBuild(type: Copy) { - from layout.projectDirectory.file("nginx-auth.conf.template") - from layout.projectDirectory.file("nginx-no-auth.conf.template") - from layout.projectDirectory.file("run.sh") - from layout.projectDirectory.file("401.html") - - into layout.buildDirectory.dir("docker") -} - -tasks.named("buildDockerImage") { - dependsOn prepareBuild - dependsOn copyDocker -} - -task bashTest(type: Exec) { - dependsOn buildDockerImage - commandLine "./test.sh" -} - -// we can't override the 'test' command, so we can make our bash test a dependency -test.dependsOn(project.tasks.bashTest) diff --git a/airbyte-proxy/gradle.properties b/airbyte-proxy/gradle.properties deleted file mode 100644 index f28927f52ca6f..0000000000000 --- a/airbyte-proxy/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=proxy diff --git a/airbyte-proxy/nginx-auth.conf.template b/airbyte-proxy/nginx-auth.conf.template deleted file mode 100644 index fe817b622536b..0000000000000 --- a/airbyte-proxy/nginx-auth.conf.template +++ /dev/null @@ -1,82 +0,0 @@ -events {} - -http { - server { - listen 8000 default_server; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - client_max_body_size 200M; - - auth_basic "Welcome to Airbyte"; - auth_basic_user_file /etc/nginx/.htpasswd; - - proxy_pass "${PROXY_PASS_WEB}"; - - proxy_connect_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_read_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - - error_page 401 /etc/nginx/401.html; - location ~ (401.html)$ { - alias /etc/nginx/$1; - auth_basic off; - } - } - } - - server { - listen 8001; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - client_max_body_size 200M; - - auth_basic "Welcome to Airbyte"; - auth_basic_user_file /etc/nginx/.htpasswd; - - proxy_pass "${PROXY_PASS_API}"; - - proxy_connect_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_read_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - - error_page 401 /etc/nginx/401.html; - location ~ (401.html)$ { - alias /etc/nginx/$1; - auth_basic off; - } - } - } - - server { - listen 8003; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - client_max_body_size 200M; - - auth_basic "Welcome to Airbyte"; - auth_basic_user_file /etc/nginx/.htpasswd; - - proxy_pass "${CONNECTOR_BUILDER_SERVER_API}"; - - error_page 401 /etc/nginx/401.html; - location ~ (401.html)$ { - alias /etc/nginx/$1; - auth_basic off; - } - } - } -} diff --git a/airbyte-proxy/nginx-no-auth.conf.template b/airbyte-proxy/nginx-no-auth.conf.template deleted file mode 100644 index 35b25c934616f..0000000000000 --- a/airbyte-proxy/nginx-no-auth.conf.template +++ /dev/null @@ -1,55 +0,0 @@ -events {} - -http { - server { - listen 8000 default_server; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - client_max_body_size 200M; - - proxy_pass "${PROXY_PASS_WEB}"; - - proxy_connect_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_read_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - } - } - - server { - listen 8001; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - client_max_body_size 200M; - - proxy_pass "${PROXY_PASS_API}"; - - proxy_connect_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - proxy_read_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - send_timeout ${BASIC_AUTH_PROXY_TIMEOUT}; - } - } - - server { - listen 8003; - - location / { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - client_max_body_size 200M; - - proxy_pass "${CONNECTOR_BUILDER_SERVER_API}"; - } - } -} diff --git a/airbyte-proxy/run.sh b/airbyte-proxy/run.sh deleted file mode 100644 index 2640263939845..0000000000000 --- a/airbyte-proxy/run.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -rm /etc/nginx/nginx.conf - -if [[ -z "${BASIC_AUTH_USERNAME}" ]]; then - echo "BASIC_AUTH_USERNAME is not set, skipping nginx auth" - - TEMPLATE_PATH="/etc/nginx/templates/nginx-no-auth.conf.template" -else - echo "BASIC_AUTH_USERNAME is set, requiring auth for user '$BASIC_AUTH_USERNAME'" - - # htpasswd for basic authentication - rm -rf /etc/nginx/.htpasswd - htpasswd -c -b /etc/nginx/.htpasswd $BASIC_AUTH_USERNAME $BASIC_AUTH_PASSWORD - - TEMPLATE_PATH="/etc/nginx/templates/nginx-auth.conf.template" -fi - -envsubst '${PROXY_PASS_WEB} ${PROXY_PASS_API} ${CONNECTOR_BUILDER_SERVER_API} ${PROXY_PASS_RESOLVER} ${BASIC_AUTH_PROXY_TIMEOUT}' < $TEMPLATE_PATH > /etc/nginx/nginx.conf - -echo "starting nginx..." -nginx -v -nginx -g "daemon off;" diff --git a/airbyte-proxy/test.sh b/airbyte-proxy/test.sh deleted file mode 100755 index c3e66d327361f..0000000000000 --- a/airbyte-proxy/test.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - -NAME="airbyte-proxy-test-container" -PORT=18000 -BASIC_AUTH_USERNAME=airbyte -BASIC_AUTH_PASSWORD=password -BASIC_AUTH_UPDATED_PASSWORD=pa55w0rd -BASIC_AUTH_PROXY_TIMEOUT=120 -TEST_HOST=localhost -VERSION="${VERSION:-dev}" # defaults to "dev", otherwise it is set by environment's $VERSION - -echo "testing with proxy container airbyte/proxy:$VERSION" - -function start_container () { - CMD="docker run -d -p $PORT:8000 --env BASIC_AUTH_USERNAME=$1 --env BASIC_AUTH_PASSWORD=$2 --env BASIC_AUTH_PROXY_TIMEOUT=$3 --env PROXY_PASS_WEB=http://localhost --env PROXY_PASS_API=http://localhost --env CONNECTOR_BUILDER_SERVER_API=http://localhost --name $NAME airbyte/proxy:$VERSION" - echo $CMD - eval $CMD - wait_for_docker; -} - -function start_container_with_proxy () { - CMD="docker run -d -p $PORT:8000 --env PROXY_PASS_WEB=$1 --env PROXY_PASS_API=$1 --name $NAME - airbyte/proxy:$VERSION" - echo $CMD - eval $CMD - wait_for_docker; -} - -function stop_container () { - echo "Stopping $NAME" - docker kill $NAME - docker rm $NAME -} - -function wait_for_docker() { - until [ "`docker inspect -f {{.State.Running}} $NAME`"=="true" ]; do - sleep 1; - done; - sleep 1; -} - -echo "Testing airbyte proxy..." - -stop_container; # just in case there was a failure of a previous test run - -echo "Starting $NAME" -start_container $BASIC_AUTH_USERNAME $BASIC_AUTH_PASSWORD $BASIC_AUTH_PROXY_TIMEOUT - -echo "Testing access without auth" -RESPONSE=`curl "http://$TEST_HOST:$PORT" -i --silent` -if [[ $RESPONSE == *"401 Unauthorized"* ]]; then - echo "✔️ access without auth blocked" -else - echo "Auth not working" - echo $RESPONSE - exit 1 -fi - -echo "Testing access with auth" -RESPONSE=`curl "http://$BASIC_AUTH_USERNAME:$BASIC_AUTH_PASSWORD@$TEST_HOST:$PORT" -i --silent` -if [[ $RESPONSE != *"401 Unauthorized"* ]]; then - echo "✔️ access with auth worked" -else - echo "Auth not working" - echo $RESPONSE - exit 1 -fi - -stop_container; - -echo "Starting $NAME with updated password" -start_container $BASIC_AUTH_USERNAME $BASIC_AUTH_UPDATED_PASSWORD $BASIC_AUTH_PROXY_TIMEOUT - -echo "Testing access with orignial paassword" -RESPONSE=`curl "http://$BASIC_AUTH_USERNAME:$BASIC_AUTH_PASSWORD@$TEST_HOST:$PORT" -i --silent` -if [[ $RESPONSE == *"401 Unauthorized"* ]]; then - echo "✔️ access with original auth blocked" -else - echo "Auth not working" - echo $RESPONSE - exit 1 -fi - -echo "Testing access updated auth" -RESPONSE=`curl "http://$BASIC_AUTH_USERNAME:$BASIC_AUTH_UPDATED_PASSWORD@$TEST_HOST:$PORT" -i --silent` -if [[ $RESPONSE != *"401 Unauthorized"* ]]; then - echo "✔️ access with updated auth worked" -else - echo "Auth not working" - echo $RESPONSE - exit 1 -fi - -stop_container; - -echo "Starting $NAME with no password" -start_container "" "" - -echo "Testing access without auth" -RESPONSE=`curl "http://$TEST_HOST:$PORT" -i --silent` -if [[ $RESPONSE != *"401 Unauthorized"* ]]; then - echo "✔️ access without auth allowed when configured" -else - echo "Auth not working" - echo $RESPONSE - exit 1 -fi - -stop_container; - - -# TODO: We can't test external URLs without a resolver, but adding a resolver that isn't dynamic+local doesn't work with docker. - -# echo "Testing that PROXY_PASS can be used to change the backend" -# start_container_with_proxy "http://www.google.com" - -# RESPONSE=`curl "http://$TEST_HOST:$PORT" -i --silent` -# if [[ $RESPONSE == *"google.com"* ]]; then -# echo "✔️ proxy backends can be changed" -# else -# echo "Proxy update not working" -# echo $RESPONSE -# exit 1 -# fi - -# stop_container; - -echo "Tests Passed ✅" -exit 0 diff --git a/airbyte-server/.gitignore b/airbyte-server/.gitignore deleted file mode 100644 index 645c924953631..0000000000000 --- a/airbyte-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -src/main/resources/openapi/config.yaml diff --git a/airbyte-server/Dockerfile b/airbyte-server/Dockerfile deleted file mode 100644 index 7ccb09c58a9c7..0000000000000 --- a/airbyte-server/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -ARG JDK_IMAGE=airbyte/airbyte-base-java-image:1.0 -FROM ${JDK_IMAGE} AS server - -EXPOSE 8000 - -ARG VERSION=0.40.32 - -ENV APPLICATION airbyte-server -ENV VERSION ${VERSION} - -WORKDIR /app - -# This is automatically unzipped by Docker -ADD bin/${APPLICATION}-${VERSION}.tar /app - -# wait for upstream dependencies to become available before starting server -ENTRYPOINT ["/bin/bash", "-c", "${APPLICATION}-${VERSION}/bin/${APPLICATION}"] diff --git a/airbyte-server/build.gradle b/airbyte-server/build.gradle deleted file mode 100644 index d88d9e30f5ff5..0000000000000 --- a/airbyte-server/build.gradle +++ /dev/null @@ -1,130 +0,0 @@ -plugins { - id 'application' -} - -configurations.all { - exclude group: 'io.micronaut.jaxrs' -} - -dependencies { - annotationProcessor platform(libs.micronaut.bom) - annotationProcessor libs.bundles.micronaut.annotation.processor - annotationProcessor libs.micronaut.jaxrs.processor - - implementation platform(libs.micronaut.bom) - implementation libs.bundles.micronaut - implementation libs.micronaut.jaxrs.server - - // Ensure that the versions defined in deps.toml are used - // instead of versions from transitive dependencies - implementation(libs.flyway.core) { - force = true - } - implementation(libs.s3) { - // Force to avoid updated version brought in transitively from Micronaut 3.8+ - // that is incompatible with our current Helm setup - force = true - } - implementation(libs.aws.java.sdk.s3) { - // Force to avoid updated version brought in transitively from Micronaut 3.8+ - // that is incompatible with our current Helm setup - force = true - } - - implementation project(':airbyte-analytics') - implementation project(':airbyte-api') - implementation project(':airbyte-commons-temporal') - implementation project(':airbyte-commons-server') - implementation project(':airbyte-commons-worker') - implementation project(':airbyte-config:init') - implementation project(':airbyte-config:config-models') - implementation project(':airbyte-config:config-persistence') - implementation project(':airbyte-config:specs') - implementation project(':airbyte-metrics:metrics-lib') - implementation project(':airbyte-db:db-lib') - implementation project(":airbyte-json-validation") - implementation project(':airbyte-notification') - implementation project(':airbyte-oauth') - implementation libs.airbyte.protocol - implementation project(':airbyte-persistence:job-persistence') - - implementation 'com.github.slugify:slugify:2.4' - implementation 'commons-cli:commons-cli:1.4' - implementation libs.temporal.sdk - implementation 'org.apache.cxf:cxf-core:3.4.2' - implementation 'org.eclipse.jetty:jetty-server:9.4.31.v20200723' - implementation 'org.eclipse.jetty:jetty-servlet:9.4.31.v20200723' - implementation 'org.glassfish.jaxb:jaxb-runtime:3.0.2' - implementation 'org.glassfish.jersey.containers:jersey-container-servlet' - implementation 'org.glassfish.jersey.inject:jersey-hk2' - implementation 'org.glassfish.jersey.media:jersey-media-json-jackson' - implementation 'org.glassfish.jersey.ext:jersey-bean-validation' - implementation 'org.quartz-scheduler:quartz:2.3.2' - implementation 'io.sentry:sentry:6.3.1' - implementation 'io.swagger:swagger-annotations:1.6.2' - - testImplementation project(':airbyte-test-utils') - testImplementation libs.postgresql - testImplementation libs.platform.testcontainers.postgresql - testImplementation 'com.squareup.okhttp3:mockwebserver:4.9.1' - testImplementation 'org.mockito:mockito-inline:4.7.0' -} - -// we want to be able to access the generated db files from config/init when we build the server docker image. -task copySeed(type: Copy, dependsOn: [project(':airbyte-config:init').processResources]) { - from "${project(':airbyte-config:init').buildDir}/resources/main/config" - into "${buildDir}/config_init/resources/main/config" -} - -// need to make sure that the files are in the resource directory before copying. -// tests require the seed to exist. -test.dependsOn(project.tasks.copySeed) -assemble.dependsOn(project.tasks.copySeed) - -mainClassName = 'io.airbyte.server.Application' - -application { - applicationName = project.name - mainClass = mainClassName - applicationDefaultJvmArgs = ['-XX:+ExitOnOutOfMemoryError', '-XX:MaxRAMPercentage=75.0'] -} - -Properties env = new Properties() -rootProject.file('.env.dev').withInputStream { env.load(it) } - -run { - // default for running on local machine. - environment "DATABASE_USER", env.DATABASE_USER - environment "DATABASE_PASSWORD", env.DATABASE_PASSWORD - - environment "CONFIG_DATABASE_USER", env.CONFIG_DATABASE_USER - environment "CONFIG_DATABASE_PASSWORD", env.CONFIG_DATABASE_PASSWORD - - // we map the docker pg db to port 5433 so it does not conflict with other pg instances. - environment "DATABASE_URL", "jdbc:postgresql://localhost:5433/${env.DATABASE_DB}" - environment "CONFIG_DATABASE_URL", "jdbc:postgresql://localhost:5433/${env.CONFIG_DATABASE_DB}" - - environment "RUN_DATABASE_MIGRATION_ON_STARTUP", "true" - - environment "WORKSPACE_ROOT", env.WORKSPACE_ROOT - environment "CONFIG_ROOT", "/tmp/airbyte_config" - environment "TRACKING_STRATEGY", env.TRACKING_STRATEGY - environment "AIRBYTE_VERSION", env.VERSION - environment "AIRBYTE_ROLE", System.getenv('AIRBYTE_ROLE') - environment "TEMPORAL_HOST", "localhost:7233" - - environment 'MICRONAUT_ENVIRONMENTS', 'control-plane' -} - -// produce reproducible archives -// (see https://docs.gradle.org/current/userguide/working_with_files.html#sec:reproducible_archives) -tasks.withType(AbstractArchiveTask) { - preserveFileTimestamps = false - reproducibleFileOrder = true -} - -tasks.named("buildDockerImage") { - dependsOn copyGeneratedTar -} - -Task publishArtifactsTask = getPublishArtifactsTask("$rootProject.ext.version", project) diff --git a/airbyte-server/gradle.properties b/airbyte-server/gradle.properties deleted file mode 100644 index 227a1c72cdcef..0000000000000 --- a/airbyte-server/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=server diff --git a/airbyte-server/readme.md b/airbyte-server/readme.md deleted file mode 100644 index a6817ac3af7b8..0000000000000 --- a/airbyte-server/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# airbyte-server - -This module contains the actual app that runs the Airbyte Configuration API. The main method can be found in `ServerApp.java`. - -The external API interface that it implements is declared in `airbyte-api`. The class that actually implements that interface is called `ConfigurationApi`. You will notice that class is very large, because generates a method for every endpoint. To keep it manageable, that class just delegates all requests to more tightly-scoped, resource-based handlers. For example, the `workspace/get` endpoint is present in `ConfigurationApi`, but all it does it delegate the call to the `WorkspaceHandler` which contains all Workspace-specific logic. Unit tests for the server happen at the Handler-level, not for the `ConfigurationApi`. diff --git a/airbyte-server/src/main/java/io/airbyte/server/Application.java b/airbyte-server/src/main/java/io/airbyte/server/Application.java deleted file mode 100644 index c1d154b542bc2..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/Application.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server; - -import io.micronaut.runtime.Micronaut; - -public class Application { - - public static void main(final String[] args) { - Micronaut.run(Application.class, args); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/CorsFilter.java b/airbyte-server/src/main/java/io/airbyte/server/CorsFilter.java deleted file mode 100644 index a99d75766e143..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/CorsFilter.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server; - -import com.google.common.collect.ImmutableMap; -import com.google.common.net.HttpHeaders; -import java.util.Map; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; - -// https://medium.com/@Leejjon_net/how-to-allow-cross-origin-requests-in-a-jax-rs-microservice-d2a6aa2df484 -public class CorsFilter implements ContainerResponseFilter { - - public static final ImmutableMap MAP = ImmutableMap.of( - HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*", - HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Origin, Content-Type, Accept, Content-Encoding, X-Airbyte-Analytic-Source", - HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTIONS, HEAD"); - - @Override - public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) { - for (final Map.Entry entry : MAP.entrySet()) { - responseContext.getHeaders().add(entry.getKey(), entry.getValue()); - } - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/DatabaseEventListener.java b/airbyte-server/src/main/java/io/airbyte/server/DatabaseEventListener.java deleted file mode 100644 index 887ab0c58bc11..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/DatabaseEventListener.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server; - -import io.airbyte.db.check.DatabaseCheckException; -import io.airbyte.db.check.DatabaseMigrationCheck; -import io.micronaut.context.event.ApplicationEventListener; -import io.micronaut.discovery.event.ServiceReadyEvent; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.lang.invoke.MethodHandles; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Singleton -public class DatabaseEventListener implements ApplicationEventListener { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private final DatabaseMigrationCheck configsMigrationCheck; - - private final DatabaseMigrationCheck jobsMigrationCheck; - - public DatabaseEventListener( - @Named("configsDatabaseMigrationCheck") final DatabaseMigrationCheck configsMigrationCheck, - @Named("jobsDatabaseMigrationCheck") final DatabaseMigrationCheck jobsMigrationCheck) { - this.configsMigrationCheck = configsMigrationCheck; - this.jobsMigrationCheck = jobsMigrationCheck; - } - - @Override - public void onApplicationEvent(final ServiceReadyEvent event) { - log.info("Checking configs database flyway migration version..."); - try { - configsMigrationCheck.check(); - } catch (final DatabaseCheckException e) { - throw new RuntimeException(e); - } - - log.info("Checking jobs database flyway migration version..."); - try { - jobsMigrationCheck.check(); - } catch (final DatabaseCheckException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/ServerApp.java b/airbyte-server/src/main/java/io/airbyte/server/ServerApp.java deleted file mode 100644 index 6cb04bf40dc97..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/ServerApp.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server; - -import io.airbyte.analytics.Deployment; -import io.airbyte.analytics.TrackingClient; -import io.airbyte.analytics.TrackingClientSingleton; -import io.airbyte.commons.features.EnvVariableFeatureFlags; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.commons.server.RequestLogger; -import io.airbyte.commons.server.errors.*; -import io.airbyte.commons.server.handlers.*; -import io.airbyte.commons.server.scheduler.DefaultSynchronousSchedulerClient; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.commons.server.scheduler.TemporalEventRunner; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.commons.temporal.ConnectionManagerUtils; -import io.airbyte.commons.temporal.NotificationUtils; -import io.airbyte.commons.temporal.StreamResetRecordsHelper; -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.temporal.TemporalUtils; -import io.airbyte.commons.temporal.TemporalWorkflowUtils; -import io.airbyte.commons.temporal.scheduling.RouterService; -import io.airbyte.commons.temporal.scheduling.TaskQueueMapper; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs; -import io.airbyte.config.helpers.LogClientSingleton; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.StatePersistence; -import io.airbyte.config.persistence.StreamResetPersistence; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.config.persistence.split_secrets.SecretsHydrator; -import io.airbyte.db.Database; -import io.airbyte.db.check.DatabaseCheckException; -import io.airbyte.db.factory.DatabaseCheckFactory; -import io.airbyte.persistence.job.DefaultJobPersistence; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.WebUrlHelper; -import io.airbyte.persistence.job.WorkspaceHelper; -import io.airbyte.persistence.job.errorreporter.JobErrorReporter; -import io.airbyte.persistence.job.errorreporter.JobErrorReportingClient; -import io.airbyte.persistence.job.errorreporter.JobErrorReportingClientFactory; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.persistence.job.tracker.JobTracker; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.airbyte.workers.helper.ConnectionHelper; -import io.temporal.client.WorkflowClient; -import io.temporal.serviceclient.WorkflowServiceStubs; -import java.net.http.HttpClient; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.flywaydb.core.Flyway; -import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletContainer; -import org.jooq.DSLContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -@SuppressWarnings("PMD.AvoidCatchingThrowable") -public class ServerApp implements ServerRunnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(ServerApp.class); - private static final int PORT = 8001; - - private final AirbyteVersion airbyteVersion; - private final Set> customComponentClasses; - private final Set customComponents; - - public ServerApp(final AirbyteVersion airbyteVersion, - final Set> customComponentClasses, - final Set customComponents) { - this.airbyteVersion = airbyteVersion; - this.customComponentClasses = customComponentClasses; - this.customComponents = customComponents; - } - - @Override - @SuppressWarnings("PMD.InvalidLogMessageFormat") - public void start() throws Exception { - final Server server = new Server(PORT); - - final ServletContextHandler handler = new ServletContextHandler(); - - final Map mdc = MDC.getCopyOfContextMap(); - - final ResourceConfig rc = - new ResourceConfig() - .register(new RequestLogger(mdc)) - .register(InvalidInputExceptionMapper.class) - .register(InvalidJsonExceptionMapper.class) - .register(InvalidJsonInputExceptionMapper.class) - .register(KnownExceptionMapper.class) - .register(UncaughtExceptionMapper.class) - .register(NotFoundExceptionMapper.class) - // needed so that the custom json exception mappers don't get overridden - // https://stackoverflow.com/questions/35669774/jersey-custom-exception-mapper-for-invalid-json-string - .register(JacksonJaxbJsonProvider.class); - - // inject custom server functionality - customComponentClasses.forEach(rc::register); - customComponents.forEach(rc::register); - - final ServletHolder configServlet = new ServletHolder(new ServletContainer(rc)); - - handler.addServlet(configServlet, "/api/*"); - - server.setHandler(handler); - - server.start(); - final String banner = MoreResources.readResource("banner/banner.txt"); - LOGGER.info(banner + String.format("Version: %s\n", airbyteVersion.serialize())); - server.join(); - - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - try { - server.stop(); - } catch (final Exception ex) { - // silently fail at this stage because server is terminating. - LOGGER.warn("exception: " + ex); - } - })); - } - - public static void assertDatabasesReady(final Configs configs, - final DSLContext configsDslContext, - final Flyway configsFlyway, - final DSLContext jobsDslContext, - final Flyway jobsFlyway) - throws DatabaseCheckException { - LOGGER.info("Checking configs database flyway migration version.."); - DatabaseCheckFactory - .createConfigsDatabaseMigrationCheck(configsDslContext, configsFlyway, configs.getConfigsDatabaseMinimumFlywayMigrationVersion(), - configs.getConfigsDatabaseInitializationTimeoutMs()) - .check(); - - LOGGER.info("Checking jobs database flyway migration version.."); - DatabaseCheckFactory.createJobsDatabaseMigrationCheck(jobsDslContext, jobsFlyway, configs.getJobsDatabaseMinimumFlywayMigrationVersion(), - configs.getJobsDatabaseInitializationTimeoutMs()).check(); - } - - public static ServerRunnable getServer(final ServerFactory apiFactory, - final Configs configs, - final DSLContext configsDslContext, - final Flyway configsFlyway, - final DSLContext jobsDslContext, - final Flyway jobsFlyway, - final TaskQueueMapper taskQueueMapper) - throws Exception { - LogClientSingleton.getInstance().setWorkspaceMdc( - configs.getWorkerEnvironment(), - configs.getLogConfigs(), - LogClientSingleton.getInstance().getServerLogsRoot(configs.getWorkspaceRoot())); - - LOGGER.info("Checking databases.."); - assertDatabasesReady(configs, configsDslContext, configsFlyway, jobsDslContext, jobsFlyway); - - LOGGER.info("Creating config repository..."); - final Database configsDatabase = new Database(configsDslContext); - final SecretsHydrator secretsHydrator = SecretPersistence.getSecretsHydrator(configsDslContext, configs); - final Optional secretPersistence = SecretPersistence.getLongLived(configsDslContext, configs); - final Optional ephemeralSecretPersistence = SecretPersistence.getEphemeral(configsDslContext, configs); - final ConfigRepository configRepository = new ConfigRepository(configsDatabase); - final SecretsRepositoryReader secretsRepositoryReader = new SecretsRepositoryReader(configRepository, secretsHydrator); - final SecretsRepositoryWriter secretsRepositoryWriter = new SecretsRepositoryWriter(configRepository, secretPersistence, - ephemeralSecretPersistence); - - LOGGER.info("Creating jobs persistence..."); - final Database jobsDatabase = new Database(jobsDslContext); - final JobPersistence jobPersistence = new DefaultJobPersistence(jobsDatabase); - - TrackingClientSingleton.initialize( - configs.getTrackingStrategy(), - new Deployment(configs.getDeploymentMode(), jobPersistence.getDeployment().orElseThrow(), configs.getWorkerEnvironment()), - configs.getAirbyteRole(), - configs.getAirbyteVersion(), - configRepository); - - final TrackingClient trackingClient = TrackingClientSingleton.get(); - final JobTracker jobTracker = new JobTracker(configRepository, jobPersistence, trackingClient); - - final FeatureFlags envVariableFeatureFlags = new EnvVariableFeatureFlags(); - - final WebUrlHelper webUrlHelper = new WebUrlHelper(configs.getWebappUrl()); - final JobErrorReportingClient jobErrorReportingClient = JobErrorReportingClientFactory.getClient(configs.getJobErrorReportingStrategy(), configs); - final JobErrorReporter jobErrorReporter = - new JobErrorReporter( - configRepository, - configs.getDeploymentMode(), - configs.getAirbyteVersionOrWarning(), - webUrlHelper, - jobErrorReportingClient); - - final TemporalUtils temporalUtils = new TemporalUtils( - configs.getTemporalCloudClientCert(), - configs.getTemporalCloudClientKey(), - configs.temporalCloudEnabled(), - configs.getTemporalCloudHost(), - configs.getTemporalCloudNamespace(), - configs.getTemporalHost(), - configs.getTemporalRetentionInDays()); - - final StreamResetPersistence streamResetPersistence = new StreamResetPersistence(configsDatabase); - final WorkflowServiceStubs temporalService = temporalUtils.createTemporalService(); - final ConnectionManagerUtils connectionManagerUtils = new ConnectionManagerUtils(); - final NotificationUtils notificationUtils = new NotificationUtils(); - final StreamResetRecordsHelper streamResetRecordsHelper = new StreamResetRecordsHelper(jobPersistence, streamResetPersistence); - - final WorkflowClient workflowClient = TemporalWorkflowUtils.createWorkflowClient(temporalService, temporalUtils.getNamespace()); - final TemporalClient temporalClient = new TemporalClient( - configs.getWorkspaceRoot(), - workflowClient, - temporalService, - streamResetPersistence, - connectionManagerUtils, - notificationUtils, - streamResetRecordsHelper); - - final OAuthConfigSupplier oAuthConfigSupplier = new OAuthConfigSupplier(configRepository, trackingClient); - RouterService routerService = new RouterService(configRepository, taskQueueMapper); - final DefaultSynchronousSchedulerClient syncSchedulerClient = - new DefaultSynchronousSchedulerClient(temporalClient, jobTracker, jobErrorReporter, oAuthConfigSupplier, routerService); - final HttpClient httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(); - final EventRunner eventRunner = new TemporalEventRunner(temporalClient); - - final WorkspaceHelper workspaceHelper = new WorkspaceHelper(configRepository, jobPersistence); - - final JsonSchemaValidator schemaValidator = new JsonSchemaValidator(); - - final AttemptHandler attemptHandler = new AttemptHandler(jobPersistence); - - final ConnectionHelper connectionHelper = new ConnectionHelper(configRepository, workspaceHelper); - - final ConnectionsHandler connectionsHandler = new ConnectionsHandler( - configRepository, - workspaceHelper, - trackingClient, - eventRunner, - connectionHelper); - - final DestinationHandler destinationHandler = new DestinationHandler( - configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - schemaValidator, - connectionsHandler, - oAuthConfigSupplier); - - final OperationsHandler operationsHandler = new OperationsHandler(configRepository); - - final SchedulerHandler schedulerHandler = new SchedulerHandler( - configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - syncSchedulerClient, - jobPersistence, - configs.getWorkerEnvironment(), - configs.getLogConfigs(), - eventRunner, - connectionsHandler, - envVariableFeatureFlags, - webUrlHelper); - - final AirbyteProtocolVersionRange airbyteProtocolVersionRange = new AirbyteProtocolVersionRange(configs.getAirbyteProtocolVersionMin(), - configs.getAirbyteProtocolVersionMax()); - - final AirbyteGithubStore airbyteGithubStore = AirbyteGithubStore.production(); - - final DestinationDefinitionsHandler destinationDefinitionsHandler = new DestinationDefinitionsHandler(configRepository, - () -> UUID.randomUUID(), - syncSchedulerClient, - airbyteGithubStore, - destinationHandler, - airbyteProtocolVersionRange); - - final HealthCheckHandler healthCheckHandler = new HealthCheckHandler(configRepository); - - final OAuthHandler oAuthHandler = new OAuthHandler(configRepository, httpClient, trackingClient, secretsRepositoryReader); - - final SourceHandler sourceHandler = new SourceHandler( - configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - schemaValidator, - connectionsHandler, - oAuthConfigSupplier); - - final SourceDefinitionsHandler sourceDefinitionsHandler = - new SourceDefinitionsHandler(configRepository, () -> UUID.randomUUID(), syncSchedulerClient, airbyteGithubStore, sourceHandler, - airbyteProtocolVersionRange); - - final JobHistoryHandler jobHistoryHandler = new JobHistoryHandler( - jobPersistence, - configs.getWorkerEnvironment(), - configs.getLogConfigs(), - connectionsHandler, - sourceHandler, - sourceDefinitionsHandler, - destinationHandler, - destinationDefinitionsHandler, - configs.getAirbyteVersion(), - temporalClient); - - final LogsHandler logsHandler = new LogsHandler(configs); - - final WorkspacesHandler workspacesHandler = new WorkspacesHandler( - configRepository, - secretsRepositoryWriter, - connectionsHandler, - destinationHandler, - sourceHandler); - - final StatePersistence statePersistence = new StatePersistence(configsDatabase); - - final StateHandler stateHandler = new StateHandler(statePersistence); - - final WebBackendConnectionsHandler webBackendConnectionsHandler = new WebBackendConnectionsHandler( - connectionsHandler, - stateHandler, - sourceHandler, - destinationHandler, - jobHistoryHandler, - schedulerHandler, - operationsHandler, - eventRunner, - configRepository); - - final WebBackendGeographiesHandler webBackendGeographiesHandler = new WebBackendGeographiesHandler(); - - final WebBackendCheckUpdatesHandler webBackendCheckUpdatesHandler = - new WebBackendCheckUpdatesHandler(configRepository, AirbyteGithubStore.production()); - - LOGGER.info("Starting server..."); - - return apiFactory.create( - syncSchedulerClient, - configRepository, - secretsRepositoryReader, - secretsRepositoryWriter, - jobPersistence, - configsDatabase, - jobsDatabase, - trackingClient, - configs.getWorkerEnvironment(), - configs.getLogConfigs(), - configs.getAirbyteVersion(), - configs.getWorkspaceRoot(), - httpClient, - eventRunner, - configsFlyway, - jobsFlyway, - attemptHandler, - connectionsHandler, - destinationDefinitionsHandler, - destinationHandler, - healthCheckHandler, - jobHistoryHandler, - logsHandler, - oAuthHandler, - new OpenApiConfigHandler(), - operationsHandler, - schedulerHandler, - sourceHandler, - sourceDefinitionsHandler, - stateHandler, - workspacesHandler, - webBackendConnectionsHandler, - webBackendGeographiesHandler, - webBackendCheckUpdatesHandler); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/ServerFactory.java b/airbyte-server/src/main/java/io/airbyte/server/ServerFactory.java deleted file mode 100644 index 19b9230916a7b..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/ServerFactory.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server; - -import io.airbyte.analytics.TrackingClient; -import io.airbyte.commons.server.handlers.*; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.helpers.LogConfigs; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.db.Database; -import io.airbyte.persistence.job.JobPersistence; -import java.net.http.HttpClient; -import java.nio.file.Path; -import java.util.HashSet; -import org.flywaydb.core.Flyway; - -public interface ServerFactory { - - ServerRunnable create(final SynchronousSchedulerClient synchronousSchedulerClient, - final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final JobPersistence jobPersistence, - final Database configsDatabase, - final Database jobsDatabase, - final TrackingClient trackingClient, - final WorkerEnvironment workerEnvironment, - final LogConfigs logConfigs, - final AirbyteVersion airbyteVersion, - final Path workspaceRoot, - final HttpClient httpClient, - final EventRunner eventRunner, - final Flyway configsFlyway, - final Flyway jobsFlyway, - final AttemptHandler attemptHandler, - final ConnectionsHandler connectionsHandler, - final DestinationDefinitionsHandler destinationDefinitionsHandler, - final DestinationHandler destinationHandler, - final HealthCheckHandler healthCheckHandler, - final JobHistoryHandler jobHistoryHandler, - final LogsHandler logsHandler, - final OAuthHandler ooAuthHandler, - final OpenApiConfigHandler openApiConfigHandler, - final OperationsHandler operationsHandler, - final SchedulerHandler schedulerHandler, - final SourceHandler sourceHandler, - final SourceDefinitionsHandler sourceDefinitionsHandler, - final StateHandler stateHandler, - final WorkspacesHandler workspacesHandler, - final WebBackendConnectionsHandler webBackendConnectionsHandler, - final WebBackendGeographiesHandler webBackendGeographiesHandler, - final WebBackendCheckUpdatesHandler webBackendCheckUpdatesHandler); - - class Api implements ServerFactory { - - @Override - public ServerRunnable create(final SynchronousSchedulerClient synchronousSchedulerClient, - final ConfigRepository configRepository, - final SecretsRepositoryReader secretsRepositoryReader, - final SecretsRepositoryWriter secretsRepositoryWriter, - final JobPersistence jobPersistence, - final Database configsDatabase, - final Database jobsDatabase, - final TrackingClient trackingClient, - final WorkerEnvironment workerEnvironment, - final LogConfigs logConfigs, - final AirbyteVersion airbyteVersion, - final Path workspaceRoot, - final HttpClient httpClient, - final EventRunner eventRunner, - final Flyway configsFlyway, - final Flyway jobsFlyway, - final AttemptHandler attemptHandler, - final ConnectionsHandler connectionsHandler, - final DestinationDefinitionsHandler destinationDefinitionsHandler, - final DestinationHandler destinationHandler, - final HealthCheckHandler healthCheckHandler, - final JobHistoryHandler jobHistoryHandler, - final LogsHandler logsHandler, - final OAuthHandler ooAuthHandler, - final OpenApiConfigHandler openApiConfigHandler, - final OperationsHandler operationsHandler, - final SchedulerHandler schedulerHandler, - final SourceHandler sourceHandler, - final SourceDefinitionsHandler sourceDefinitionsHandler, - final StateHandler stateHandler, - final WorkspacesHandler workspacesHandler, - final WebBackendConnectionsHandler webBackendConnectionsHandler, - final WebBackendGeographiesHandler webBackendGeographiesHandler, - final WebBackendCheckUpdatesHandler webBackendCheckUpdatesHandler) { - - // construct server - return new ServerApp(airbyteVersion, new HashSet<>(), new HashSet<>()); - } - - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/ServerRunnable.java b/airbyte-server/src/main/java/io/airbyte/server/ServerRunnable.java deleted file mode 100644 index 4668ff84251a1..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/ServerRunnable.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server; - -public interface ServerRunnable { - - void start() throws Exception; - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/ApiHelper.java b/airbyte-server/src/main/java/io/airbyte/server/apis/ApiHelper.java deleted file mode 100644 index de4cdbd3c30fa..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/ApiHelper.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import io.airbyte.commons.server.errors.BadObjectSchemaKnownException; -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.config.persistence.ConfigNotFoundException; -import io.airbyte.validation.json.JsonValidationException; -import java.io.IOException; -import org.slf4j.LoggerFactory; - -public class ApiHelper { - - static T execute(final HandlerCall call) { - try { - return call.call(); - } catch (final ConfigNotFoundException e) { - throw new IdNotFoundKnownException(String.format("Could not find configuration for %s: %s.", e.getType(), e.getConfigId()), - e.getConfigId(), e); - } catch (final JsonValidationException e) { - throw new BadObjectSchemaKnownException( - String.format("The provided configuration does not fulfill the specification. Errors: %s", e.getMessage()), e); - } catch (final IOException e) { - throw new RuntimeException(e); - } catch (final Exception e) { - LoggerFactory.getLogger(ApiHelper.class).error("Unexpected Exception", e); - throw e; - } - } - - interface HandlerCall { - - T call() throws ConfigNotFoundException, IOException, JsonValidationException; - - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/AttemptApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/AttemptApiController.java deleted file mode 100644 index 9c6949b9b36e4..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/AttemptApiController.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; - -import io.airbyte.api.generated.AttemptApi; -import io.airbyte.api.model.generated.InternalOperationResult; -import io.airbyte.api.model.generated.SaveAttemptSyncConfigRequestBody; -import io.airbyte.api.model.generated.SaveStatsRequestBody; -import io.airbyte.api.model.generated.SetWorkflowInAttemptRequestBody; -import io.airbyte.commons.server.handlers.AttemptHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/attempt/") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class AttemptApiController implements AttemptApi { - - private final AttemptHandler attemptHandler; - - public AttemptApiController(final AttemptHandler attemptHandler) { - this.attemptHandler = attemptHandler; - } - - @Override - @Post(uri = "/save_stats", - processes = MediaType.APPLICATION_JSON) - public InternalOperationResult saveStats(final SaveStatsRequestBody requestBody) { - return ApiHelper.execute(() -> attemptHandler.saveStats(requestBody)); - } - - @Override - @Post(uri = "/set_workflow_in_attempt", - processes = MediaType.APPLICATION_JSON) - @Secured({ADMIN}) - public InternalOperationResult setWorkflowInAttempt(@Body final SetWorkflowInAttemptRequestBody requestBody) { - return ApiHelper.execute(() -> attemptHandler.setWorkflowInAttempt(requestBody)); - } - - @Override - @Post(uri = "/save_sync_config", - processes = MediaType.APPLICATION_JSON) - @Secured({ADMIN}) - public InternalOperationResult saveSyncConfig(@Body final SaveAttemptSyncConfigRequestBody requestBody) { - return ApiHelper.execute(() -> attemptHandler.saveSyncConfig(requestBody)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/ConnectionApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/ConnectionApiController.java deleted file mode 100644 index 5a86ff1dfa544..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/ConnectionApiController.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.ConnectionApi; -import io.airbyte.api.model.generated.ConnectionCreate; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; -import io.airbyte.api.model.generated.ConnectionSearch; -import io.airbyte.api.model.generated.ConnectionUpdate; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.ConnectionsHandler; -import io.airbyte.commons.server.handlers.OperationsHandler; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.micronaut.context.annotation.Context; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/connections") -@Context() -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class ConnectionApiController implements ConnectionApi { - - private final ConnectionsHandler connectionsHandler; - private final OperationsHandler operationsHandler; - private final SchedulerHandler schedulerHandler; - - public ConnectionApiController(final ConnectionsHandler connectionsHandler, - final OperationsHandler operationsHandler, - final SchedulerHandler schedulerHandler) { - this.connectionsHandler = connectionsHandler; - this.operationsHandler = operationsHandler; - this.schedulerHandler = schedulerHandler; - } - - @Override - @Post(uri = "/create") - @Secured({EDITOR}) - @SecuredWorkspace - public ConnectionRead createConnection(@Body final ConnectionCreate connectionCreate) { - return ApiHelper.execute(() -> connectionsHandler.createConnection(connectionCreate)); - } - - @Override - @Post(uri = "/update") - @Secured({EDITOR}) - @SecuredWorkspace - public ConnectionRead updateConnection(@Body final ConnectionUpdate connectionUpdate) { - return ApiHelper.execute(() -> connectionsHandler.updateConnection(connectionUpdate)); - } - - @Override - @Post(uri = "/list") - @Secured({READER}) - @SecuredWorkspace - public ConnectionReadList listConnectionsForWorkspace(@Body final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody)); - } - - @Override - @Post(uri = "/list_all") - @Secured({READER}) - @SecuredWorkspace - public ConnectionReadList listAllConnectionsForWorkspace(@Body final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> connectionsHandler.listAllConnectionsForWorkspace(workspaceIdRequestBody)); - } - - @Override - @Post(uri = "/search") - public ConnectionReadList searchConnections(@Body final ConnectionSearch connectionSearch) { - return ApiHelper.execute(() -> connectionsHandler.searchConnections(connectionSearch)); - } - - @Override - @Post(uri = "/get") - @Secured({READER}) - @SecuredWorkspace - public ConnectionRead getConnection(@Body final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> connectionsHandler.getConnection(connectionIdRequestBody.getConnectionId())); - } - - @Override - @Post(uri = "/delete") - @Status(HttpStatus.NO_CONTENT) - @Secured({EDITOR}) - @SecuredWorkspace - public void deleteConnection(@Body final ConnectionIdRequestBody connectionIdRequestBody) { - ApiHelper.execute(() -> { - operationsHandler.deleteOperationsForConnection(connectionIdRequestBody); - connectionsHandler.deleteConnection(connectionIdRequestBody.getConnectionId()); - return null; - }); - } - - @Override - @Post(uri = "/sync") - @Secured({EDITOR}) - @SecuredWorkspace - public JobInfoRead syncConnection(@Body final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> schedulerHandler.syncConnection(connectionIdRequestBody)); - } - - @Override - @Post(uri = "/reset") - @Secured({EDITOR}) - @SecuredWorkspace - public JobInfoRead resetConnection(@Body final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> schedulerHandler.resetConnection(connectionIdRequestBody)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationApiController.java deleted file mode 100644 index d594124f998c2..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationApiController.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.DestinationApi; -import io.airbyte.api.model.generated.CheckConnectionRead; -import io.airbyte.api.model.generated.DestinationCloneRequestBody; -import io.airbyte.api.model.generated.DestinationCreate; -import io.airbyte.api.model.generated.DestinationIdRequestBody; -import io.airbyte.api.model.generated.DestinationRead; -import io.airbyte.api.model.generated.DestinationReadList; -import io.airbyte.api.model.generated.DestinationSearch; -import io.airbyte.api.model.generated.DestinationUpdate; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.DestinationHandler; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/destinations") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class DestinationApiController implements DestinationApi { - - private final DestinationHandler destinationHandler; - private final SchedulerHandler schedulerHandler; - - public DestinationApiController(final DestinationHandler destinationHandler, final SchedulerHandler schedulerHandler) { - this.destinationHandler = destinationHandler; - this.schedulerHandler = schedulerHandler; - } - - @Post(uri = "/check_connection") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public CheckConnectionRead checkConnectionToDestination(@Body final DestinationIdRequestBody destinationIdRequestBody) { - return ApiHelper.execute(() -> schedulerHandler.checkDestinationConnectionFromDestinationId(destinationIdRequestBody)); - } - - @Post(uri = "/check_connection_for_update") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public CheckConnectionRead checkConnectionToDestinationForUpdate(@Body final DestinationUpdate destinationUpdate) { - return ApiHelper.execute(() -> schedulerHandler.checkDestinationConnectionFromDestinationIdForUpdate(destinationUpdate)); - } - - @Post(uri = "/clone") - @Override - public DestinationRead cloneDestination(@Body final DestinationCloneRequestBody destinationCloneRequestBody) { - return ApiHelper.execute(() -> destinationHandler.cloneDestination(destinationCloneRequestBody)); - } - - @Post(uri = "/create") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public DestinationRead createDestination(@Body final DestinationCreate destinationCreate) { - return ApiHelper.execute(() -> destinationHandler.createDestination(destinationCreate)); - } - - @Post(uri = "/delete") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - @Status(HttpStatus.NO_CONTENT) - public void deleteDestination(@Body final DestinationIdRequestBody destinationIdRequestBody) { - ApiHelper.execute(() -> { - destinationHandler.deleteDestination(destinationIdRequestBody); - return null; - }); - } - - @Post(uri = "/get") - @Secured({READER}) - @SecuredWorkspace - @Override - public DestinationRead getDestination(@Body final DestinationIdRequestBody destinationIdRequestBody) { - return ApiHelper.execute(() -> destinationHandler.getDestination(destinationIdRequestBody)); - } - - @Post(uri = "/list") - @Secured({READER}) - @SecuredWorkspace - @Override - public DestinationReadList listDestinationsForWorkspace(@Body final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> destinationHandler.listDestinationsForWorkspace(workspaceIdRequestBody)); - } - - @Post(uri = "/search") - @Override - public DestinationReadList searchDestinations(@Body final DestinationSearch destinationSearch) { - return ApiHelper.execute(() -> destinationHandler.searchDestinations(destinationSearch)); - } - - @Post(uri = "/update") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public DestinationRead updateDestination(@Body final DestinationUpdate destinationUpdate) { - return ApiHelper.execute(() -> destinationHandler.updateDestination(destinationUpdate)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionApiController.java deleted file mode 100644 index 2f86a587082f6..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionApiController.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.DestinationDefinitionApi; -import io.airbyte.api.model.generated.CustomDestinationDefinitionCreate; -import io.airbyte.api.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.DestinationDefinitionRead; -import io.airbyte.api.model.generated.DestinationDefinitionReadList; -import io.airbyte.api.model.generated.DestinationDefinitionUpdate; -import io.airbyte.api.model.generated.PrivateDestinationDefinitionRead; -import io.airbyte.api.model.generated.PrivateDestinationDefinitionReadList; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.DestinationDefinitionsHandler; -import io.micronaut.context.annotation.Context; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/destination_definitions") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Context -@Secured(SecurityRule.IS_AUTHENTICATED) -public class DestinationDefinitionApiController implements DestinationDefinitionApi { - - private final DestinationDefinitionsHandler destinationDefinitionsHandler; - - public DestinationDefinitionApiController(final DestinationDefinitionsHandler destinationDefinitionsHandler) { - this.destinationDefinitionsHandler = destinationDefinitionsHandler; - } - - @Post(uri = "/create_custom") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public DestinationDefinitionRead createCustomDestinationDefinition(final CustomDestinationDefinitionCreate customDestinationDefinitionCreate) { - return ApiHelper.execute(() -> destinationDefinitionsHandler.createCustomDestinationDefinition(customDestinationDefinitionCreate)); - } - - @Post(uri = "/delete") - @Secured({ADMIN}) - @Override - @Status(HttpStatus.NO_CONTENT) - public void deleteDestinationDefinition(final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody) { - ApiHelper.execute(() -> { - destinationDefinitionsHandler.deleteDestinationDefinition(destinationDefinitionIdRequestBody); - return null; - }); - } - - @Post(uri = "/get") - @Secured({AUTHENTICATED_USER}) - @Override - public DestinationDefinitionRead getDestinationDefinition(final DestinationDefinitionIdRequestBody destinationDefinitionIdRequestBody) { - return ApiHelper.execute(() -> destinationDefinitionsHandler.getDestinationDefinition(destinationDefinitionIdRequestBody)); - } - - @Post(uri = "/get_for_workspace") - @Secured({READER}) - @SecuredWorkspace - @Override - public DestinationDefinitionRead getDestinationDefinitionForWorkspace(final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) { - return ApiHelper.execute(() -> destinationDefinitionsHandler.getDestinationDefinitionForWorkspace(destinationDefinitionIdWithWorkspaceId)); - } - - @Post(uri = "/grant_definition") - @Secured({ADMIN}) - @Override - public PrivateDestinationDefinitionRead grantDestinationDefinitionToWorkspace(final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) { - return ApiHelper - .execute(() -> destinationDefinitionsHandler.grantDestinationDefinitionToWorkspace(destinationDefinitionIdWithWorkspaceId)); - } - - @Post(uri = "/list") - @Secured({AUTHENTICATED_USER}) - @Override - public DestinationDefinitionReadList listDestinationDefinitions() { - return ApiHelper.execute(destinationDefinitionsHandler::listDestinationDefinitions); - } - - @Post(uri = "/list_for_workspace") - @Secured({READER}) - @SecuredWorkspace - @Override - public DestinationDefinitionReadList listDestinationDefinitionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> destinationDefinitionsHandler.listDestinationDefinitionsForWorkspace(workspaceIdRequestBody)); - } - - @Post(uri = "/list_latest") - @Secured({AUTHENTICATED_USER}) - @Override - public DestinationDefinitionReadList listLatestDestinationDefinitions() { - return ApiHelper.execute(destinationDefinitionsHandler::listLatestDestinationDefinitions); - } - - @Post(uri = "/list_private") - @Secured({ADMIN}) - @Override - public PrivateDestinationDefinitionReadList listPrivateDestinationDefinitions(final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> destinationDefinitionsHandler.listPrivateDestinationDefinitions(workspaceIdRequestBody)); - } - - @Post(uri = "/revoke_definition") - @Secured({ADMIN}) - @Override - public void revokeDestinationDefinitionFromWorkspace(final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) { - ApiHelper.execute(() -> { - destinationDefinitionsHandler.revokeDestinationDefinitionFromWorkspace(destinationDefinitionIdWithWorkspaceId); - return null; - }); - } - - @Post(uri = "/update") - @Secured({AUTHENTICATED_USER}) - @Override - public DestinationDefinitionRead updateDestinationDefinition(final DestinationDefinitionUpdate destinationDefinitionUpdate) { - return ApiHelper.execute(() -> destinationDefinitionsHandler.updateDestinationDefinition(destinationDefinitionUpdate)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionSpecificationApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionSpecificationApiController.java deleted file mode 100644 index 92dc7cae20e8c..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationDefinitionSpecificationApiController.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; - -import io.airbyte.api.generated.DestinationDefinitionSpecificationApi; -import io.airbyte.api.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.DestinationDefinitionSpecificationRead; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/destination_definition_specifications") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class DestinationDefinitionSpecificationApiController implements DestinationDefinitionSpecificationApi { - - private final SchedulerHandler schedulerHandler; - - public DestinationDefinitionSpecificationApiController(final SchedulerHandler schedulerHandler) { - this.schedulerHandler = schedulerHandler; - } - - @Post("/get") - @Secured({AUTHENTICATED_USER}) - @Override - public DestinationDefinitionSpecificationRead getDestinationDefinitionSpecification(final DestinationDefinitionIdWithWorkspaceId destinationDefinitionIdWithWorkspaceId) { - return ApiHelper.execute(() -> schedulerHandler.getDestinationSpecification(destinationDefinitionIdWithWorkspaceId)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationOauthApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationOauthApiController.java deleted file mode 100644 index 7b747dafa47f8..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/DestinationOauthApiController.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; - -import io.airbyte.api.generated.DestinationOauthApi; -import io.airbyte.api.model.generated.CompleteDestinationOAuthRequest; -import io.airbyte.api.model.generated.DestinationOauthConsentRequest; -import io.airbyte.api.model.generated.OAuthConsentRead; -import io.airbyte.api.model.generated.SetInstancewideDestinationOauthParamsRequestBody; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.OAuthHandler; -import io.micronaut.context.annotation.Context; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import java.util.Map; - -@Controller("/api/v1/destination_oauths") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Context -@Secured(SecurityRule.IS_AUTHENTICATED) -public class DestinationOauthApiController implements DestinationOauthApi { - - private final OAuthHandler oAuthHandler; - - public DestinationOauthApiController(final OAuthHandler oAuthHandler) { - this.oAuthHandler = oAuthHandler; - } - - @Post("/complete_oauth") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public Map completeDestinationOAuth(final CompleteDestinationOAuthRequest completeDestinationOAuthRequest) { - return ApiHelper.execute(() -> oAuthHandler.completeDestinationOAuth(completeDestinationOAuthRequest)); - } - - @Post("/get_consent_url") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public OAuthConsentRead getDestinationOAuthConsent(final DestinationOauthConsentRequest destinationOauthConsentRequest) { - return ApiHelper.execute(() -> oAuthHandler.getDestinationOAuthConsent(destinationOauthConsentRequest)); - } - - @Post("/oauth_params/create") - @Secured({ADMIN}) - @Override - public void setInstancewideDestinationOauthParams(final SetInstancewideDestinationOauthParamsRequestBody setInstancewideDestinationOauthParamsRequestBody) { - ApiHelper.execute(() -> { - oAuthHandler.setDestinationInstancewideOauthParams(setInstancewideDestinationOauthParamsRequestBody); - return null; - }); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/HealthApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/HealthApiController.java deleted file mode 100644 index 0e8622c52ddd3..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/HealthApiController.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import io.airbyte.api.generated.HealthApi; -import io.airbyte.api.model.generated.HealthCheckRead; -import io.airbyte.commons.server.handlers.HealthCheckHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Get; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/health") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_ANONYMOUS) -public class HealthApiController implements HealthApi { - - private final HealthCheckHandler healthCheckHandler; - - public HealthApiController(final HealthCheckHandler healthCheckHandler) { - this.healthCheckHandler = healthCheckHandler; - } - - @Override - @Get(produces = MediaType.APPLICATION_JSON) - public HealthCheckRead getHealthCheck() { - return healthCheckHandler.health(); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/JobsApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/JobsApiController.java deleted file mode 100644 index 4fc06076ab28b..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/JobsApiController.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.JobsApi; -import io.airbyte.api.model.generated.AttemptNormalizationStatusReadList; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.JobDebugInfoRead; -import io.airbyte.api.model.generated.JobIdRequestBody; -import io.airbyte.api.model.generated.JobInfoLightRead; -import io.airbyte.api.model.generated.JobInfoRead; -import io.airbyte.api.model.generated.JobListRequestBody; -import io.airbyte.api.model.generated.JobOptionalRead; -import io.airbyte.api.model.generated.JobReadList; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.JobHistoryHandler; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.micronaut.context.annotation.Context; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/jobs") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Context -@Secured(SecurityRule.IS_AUTHENTICATED) -public class JobsApiController implements JobsApi { - - private final JobHistoryHandler jobHistoryHandler; - private final SchedulerHandler schedulerHandler; - - public JobsApiController(final JobHistoryHandler jobHistoryHandler, final SchedulerHandler schedulerHandler) { - this.jobHistoryHandler = jobHistoryHandler; - this.schedulerHandler = schedulerHandler; - } - - @Post("/cancel") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public JobInfoRead cancelJob(final JobIdRequestBody jobIdRequestBody) { - return ApiHelper.execute(() -> schedulerHandler.cancelJob(jobIdRequestBody)); - } - - @Post("/get_normalization_status") - @Secured({ADMIN}) - @Override - public AttemptNormalizationStatusReadList getAttemptNormalizationStatusesForJob(final JobIdRequestBody jobIdRequestBody) { - return ApiHelper.execute(() -> jobHistoryHandler.getAttemptNormalizationStatuses(jobIdRequestBody)); - } - - @Post("/get_debug_info") - @Secured({READER}) - @SecuredWorkspace - @Override - public JobDebugInfoRead getJobDebugInfo(final JobIdRequestBody jobIdRequestBody) { - return ApiHelper.execute(() -> jobHistoryHandler.getJobDebugInfo(jobIdRequestBody)); - } - - @Post("/get") - @Secured({READER}) - @SecuredWorkspace - @Override - public JobInfoRead getJobInfo(final JobIdRequestBody jobIdRequestBody) { - return ApiHelper.execute(() -> jobHistoryHandler.getJobInfo(jobIdRequestBody)); - } - - @Post("/get_light") - @Secured({READER}) - @SecuredWorkspace - @Override - public JobInfoLightRead getJobInfoLight(final JobIdRequestBody jobIdRequestBody) { - return ApiHelper.execute(() -> jobHistoryHandler.getJobInfoLight(jobIdRequestBody)); - } - - @Post("/get_last_replication_job") - @Secured({READER}) - @Override - public JobOptionalRead getLastReplicationJob(final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> jobHistoryHandler.getLastReplicationJob(connectionIdRequestBody)); - } - - @Post("/list") - @Secured({READER}) - @SecuredWorkspace - @Override - public JobReadList listJobsFor(final JobListRequestBody jobListRequestBody) { - return ApiHelper.execute(() -> jobHistoryHandler.listJobsFor(jobListRequestBody)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/LogsApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/LogsApiController.java deleted file mode 100644 index 97e1050fc518a..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/LogsApiController.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; - -import io.airbyte.api.generated.LogsApi; -import io.airbyte.api.model.generated.LogsRequestBody; -import io.airbyte.commons.server.handlers.LogsHandler; -import io.micronaut.context.annotation.Context; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import java.io.File; - -@Controller("/api/v1/logs") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Context -@Secured(SecurityRule.IS_AUTHENTICATED) -public class LogsApiController implements LogsApi { - - private final LogsHandler logsHandler; - - public LogsApiController(final LogsHandler logsHandler) { - this.logsHandler = logsHandler; - } - - @Post("/get") - @Secured({ADMIN}) - @Override - public File getLogs(final LogsRequestBody logsRequestBody) { - return ApiHelper.execute(() -> logsHandler.getLogs(logsRequestBody)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/NotFoundController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/NotFoundController.java deleted file mode 100644 index d278cde04c5d0..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/NotFoundController.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Error; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -/** - * Custom controller that handles global 404 responses for unknown/unmapped paths. - */ -@Controller("/api/notfound") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_ANONYMOUS) -public class NotFoundController { - - @Error(status = HttpStatus.NOT_FOUND, - global = true) - public HttpResponse notFound(final HttpRequest request) { - // Would like to send the id along but we don't have access to the http request anymore to fetch it - // from. TODO: Come back to this with issue #4189 - return HttpResponse.status(HttpStatus.NOT_FOUND) - .body("Object not found.") - .contentType(MediaType.APPLICATION_JSON); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/NotificationsApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/NotificationsApiController.java deleted file mode 100644 index cf8c0a57180d0..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/NotificationsApiController.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; - -import io.airbyte.api.generated.NotificationsApi; -import io.airbyte.api.model.generated.Notification; -import io.airbyte.api.model.generated.NotificationRead; -import io.airbyte.api.model.generated.NotificationRead.StatusEnum; -import io.airbyte.commons.server.converters.NotificationConverter; -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.notification.NotificationClient; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import java.io.IOException; - -@Controller("/api/v1/notifications/try") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class NotificationsApiController implements NotificationsApi { - - public NotificationsApiController() {} - - @Post - @Secured({AUTHENTICATED_USER}) - @Override - public NotificationRead tryNotificationConfig(@Body final Notification notification) { - return ApiHelper.execute(() -> tryNotification(notification)); - } - - private NotificationRead tryNotification(final Notification notification) { - try { - final NotificationClient notificationClient = NotificationClient.createNotificationClient(NotificationConverter.toConfig(notification)); - final String messageFormat = "Hello World! This is a test from Airbyte to try %s notification settings for sync %s"; - final boolean failureNotified = notificationClient.notifyFailure(String.format(messageFormat, notification.getNotificationType(), "failures")); - final boolean successNotified = notificationClient.notifySuccess(String.format(messageFormat, notification.getNotificationType(), "successes")); - if (failureNotified || successNotified) { - return new NotificationRead().status(StatusEnum.SUCCEEDED); - } - } catch (final IllegalArgumentException e) { - throw new IdNotFoundKnownException(e.getMessage(), notification.getNotificationType().name(), e); - } catch (final IOException | InterruptedException e) { - return new NotificationRead().status(StatusEnum.FAILED).message(e.getMessage()); - } - return new NotificationRead().status(StatusEnum.FAILED); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/OpenapiApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/OpenapiApiController.java deleted file mode 100644 index ee5b4b6d0be85..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/OpenapiApiController.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; - -import io.airbyte.api.generated.OpenapiApi; -import io.airbyte.commons.server.handlers.OpenApiConfigHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Get; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import java.io.File; - -@Controller("/api/v1/openapi") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class OpenapiApiController implements OpenapiApi { - - private final OpenApiConfigHandler openApiConfigHandler; - - public OpenapiApiController(final OpenApiConfigHandler openApiConfigHandler) { - this.openApiConfigHandler = openApiConfigHandler; - } - - @Get(produces = "text/plain") - @Secured({AUTHENTICATED_USER}) - @Override - public File getOpenApiSpec() { - return ApiHelper.execute(openApiConfigHandler::getFile); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/OperationApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/OperationApiController.java deleted file mode 100644 index 8065ea9280b66..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/OperationApiController.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.OperationApi; -import io.airbyte.api.model.generated.CheckOperationRead; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.OperationCreate; -import io.airbyte.api.model.generated.OperationIdRequestBody; -import io.airbyte.api.model.generated.OperationRead; -import io.airbyte.api.model.generated.OperationReadList; -import io.airbyte.api.model.generated.OperationUpdate; -import io.airbyte.api.model.generated.OperatorConfiguration; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.OperationsHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/operations") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class OperationApiController implements OperationApi { - - private final OperationsHandler operationsHandler; - - public OperationApiController(final OperationsHandler operationsHandler) { - this.operationsHandler = operationsHandler; - } - - @Post("/check") - @Secured({AUTHENTICATED_USER}) - @Override - public CheckOperationRead checkOperation(@Body final OperatorConfiguration operatorConfiguration) { - return ApiHelper.execute(() -> operationsHandler.checkOperation(operatorConfiguration)); - } - - @Post("/create") - @Override - @Secured({EDITOR}) - @SecuredWorkspace - public OperationRead createOperation(@Body final OperationCreate operationCreate) { - return ApiHelper.execute(() -> operationsHandler.createOperation(operationCreate)); - } - - @Post("/delete") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - @Status(HttpStatus.NO_CONTENT) - public void deleteOperation(@Body final OperationIdRequestBody operationIdRequestBody) { - ApiHelper.execute(() -> { - operationsHandler.deleteOperation(operationIdRequestBody); - return null; - }); - } - - @Post("/get") - @Secured({READER}) - @SecuredWorkspace - @Override - public OperationRead getOperation(@Body final OperationIdRequestBody operationIdRequestBody) { - return ApiHelper.execute(() -> operationsHandler.getOperation(operationIdRequestBody)); - } - - @Post("/list") - @Secured({READER}) - @SecuredWorkspace - @Override - public OperationReadList listOperationsForConnection(@Body final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> operationsHandler.listOperationsForConnection(connectionIdRequestBody)); - } - - @Post("/update") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public OperationRead updateOperation(@Body final OperationUpdate operationUpdate) { - return ApiHelper.execute(() -> operationsHandler.updateOperation(operationUpdate)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/SchedulerApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/SchedulerApiController.java deleted file mode 100644 index d7a5edf6f6523..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/SchedulerApiController.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; - -import io.airbyte.api.generated.SchedulerApi; -import io.airbyte.api.model.generated.CheckConnectionRead; -import io.airbyte.api.model.generated.DestinationCoreConfig; -import io.airbyte.api.model.generated.SourceCoreConfig; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRead; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/scheduler") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class SchedulerApiController implements SchedulerApi { - - private final SchedulerHandler schedulerHandler; - - public SchedulerApiController(final SchedulerHandler schedulerHandler) { - this.schedulerHandler = schedulerHandler; - } - - @Post("/destinations/check_connection") - @Secured({AUTHENTICATED_USER}) - @Override - public CheckConnectionRead executeDestinationCheckConnection(final DestinationCoreConfig destinationCoreConfig) { - return ApiHelper.execute(() -> schedulerHandler.checkDestinationConnectionFromDestinationCreate(destinationCoreConfig)); - } - - @Post("/sources/check_connection") - @Secured({AUTHENTICATED_USER}) - @Override - public CheckConnectionRead executeSourceCheckConnection(final SourceCoreConfig sourceCoreConfig) { - return ApiHelper.execute(() -> schedulerHandler.checkSourceConnectionFromSourceCreate(sourceCoreConfig)); - } - - @Post("/sources/discover_schema") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public SourceDiscoverSchemaRead executeSourceDiscoverSchema(final SourceCoreConfig sourceCoreConfig) { - return ApiHelper.execute(() -> schedulerHandler.discoverSchemaForSourceFromSourceCreate(sourceCoreConfig)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/SourceApiController.java deleted file mode 100644 index 4ad1f408ff059..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceApiController.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.SourceApi; -import io.airbyte.api.model.generated.ActorCatalogWithUpdatedAt; -import io.airbyte.api.model.generated.CheckConnectionRead; -import io.airbyte.api.model.generated.DiscoverCatalogResult; -import io.airbyte.api.model.generated.SourceCloneRequestBody; -import io.airbyte.api.model.generated.SourceCreate; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRead; -import io.airbyte.api.model.generated.SourceDiscoverSchemaRequestBody; -import io.airbyte.api.model.generated.SourceDiscoverSchemaWriteRequestBody; -import io.airbyte.api.model.generated.SourceIdRequestBody; -import io.airbyte.api.model.generated.SourceRead; -import io.airbyte.api.model.generated.SourceReadList; -import io.airbyte.api.model.generated.SourceSearch; -import io.airbyte.api.model.generated.SourceUpdate; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.airbyte.commons.server.handlers.SourceHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/sources") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class SourceApiController implements SourceApi { - - private final SchedulerHandler schedulerHandler; - private final SourceHandler sourceHandler; - - public SourceApiController(final SchedulerHandler schedulerHandler, final SourceHandler sourceHandler) { - this.schedulerHandler = schedulerHandler; - this.sourceHandler = sourceHandler; - } - - @Post("/check_connection") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public CheckConnectionRead checkConnectionToSource(final SourceIdRequestBody sourceIdRequestBody) { - return ApiHelper.execute(() -> schedulerHandler.checkSourceConnectionFromSourceId(sourceIdRequestBody)); - } - - @Post("/check_connection_for_update") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public CheckConnectionRead checkConnectionToSourceForUpdate(final SourceUpdate sourceUpdate) { - return ApiHelper.execute(() -> schedulerHandler.checkSourceConnectionFromSourceIdForUpdate(sourceUpdate)); - } - - @Post("/clone") - @Override - public SourceRead cloneSource(final SourceCloneRequestBody sourceCloneRequestBody) { - return ApiHelper.execute(() -> sourceHandler.cloneSource(sourceCloneRequestBody)); - } - - @Post("/create") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public SourceRead createSource(final SourceCreate sourceCreate) { - return ApiHelper.execute(() -> sourceHandler.createSource(sourceCreate)); - } - - @Post("/delete") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - @Status(HttpStatus.NO_CONTENT) - public void deleteSource(final SourceIdRequestBody sourceIdRequestBody) { - ApiHelper.execute(() -> { - sourceHandler.deleteSource(sourceIdRequestBody); - return null; - }); - } - - @Post("/discover_schema") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public SourceDiscoverSchemaRead discoverSchemaForSource(final SourceDiscoverSchemaRequestBody sourceDiscoverSchemaRequestBody) { - return ApiHelper.execute(() -> schedulerHandler.discoverSchemaForSourceFromSourceId(sourceDiscoverSchemaRequestBody)); - } - - @Post("/get") - @Secured({READER}) - @SecuredWorkspace - @Override - public SourceRead getSource(final SourceIdRequestBody sourceIdRequestBody) { - return ApiHelper.execute(() -> sourceHandler.getSource(sourceIdRequestBody)); - } - - @Post("/most_recent_source_actor_catalog") - @Secured({READER}) - @SecuredWorkspace - @Override - public ActorCatalogWithUpdatedAt getMostRecentSourceActorCatalog(final SourceIdRequestBody sourceIdRequestBody) { - return ApiHelper.execute(() -> sourceHandler.getMostRecentSourceActorCatalogWithUpdatedAt(sourceIdRequestBody)); - } - - @Post("/list") - @Secured({READER}) - @SecuredWorkspace - @Override - public SourceReadList listSourcesForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> sourceHandler.listSourcesForWorkspace(workspaceIdRequestBody)); - } - - @Post("/search") - @Override - public SourceReadList searchSources(final SourceSearch sourceSearch) { - return ApiHelper.execute(() -> sourceHandler.searchSources(sourceSearch)); - } - - @Post("/update") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public SourceRead updateSource(final SourceUpdate sourceUpdate) { - return ApiHelper.execute(() -> sourceHandler.updateSource(sourceUpdate)); - } - - @Post("/write_discover_catalog_result") - @Override - public DiscoverCatalogResult writeDiscoverCatalogResult(final SourceDiscoverSchemaWriteRequestBody request) { - return ApiHelper.execute(() -> sourceHandler.writeDiscoverCatalogResult(request)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionApiController.java deleted file mode 100644 index f7d3a233b03d7..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionApiController.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.SourceDefinitionApi; -import io.airbyte.api.model.generated.CustomSourceDefinitionCreate; -import io.airbyte.api.model.generated.PrivateSourceDefinitionRead; -import io.airbyte.api.model.generated.PrivateSourceDefinitionReadList; -import io.airbyte.api.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.SourceDefinitionRead; -import io.airbyte.api.model.generated.SourceDefinitionReadList; -import io.airbyte.api.model.generated.SourceDefinitionUpdate; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.SourceDefinitionsHandler; -import io.micronaut.context.annotation.Context; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/source_definitions") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Context -@Secured(SecurityRule.IS_AUTHENTICATED) -public class SourceDefinitionApiController implements SourceDefinitionApi { - - private final SourceDefinitionsHandler sourceDefinitionsHandler; - - public SourceDefinitionApiController(final SourceDefinitionsHandler sourceDefinitionsHandler) { - this.sourceDefinitionsHandler = sourceDefinitionsHandler; - } - - @Post("/create_custom") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public SourceDefinitionRead createCustomSourceDefinition(final CustomSourceDefinitionCreate customSourceDefinitionCreate) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.createCustomSourceDefinition(customSourceDefinitionCreate)); - } - - @Post("/delete") - @Secured({ADMIN}) - @Override - @Status(HttpStatus.NO_CONTENT) - public void deleteSourceDefinition(final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody) { - ApiHelper.execute(() -> { - sourceDefinitionsHandler.deleteSourceDefinition(sourceDefinitionIdRequestBody); - return null; - }); - } - - @Post("/get") - @Secured({AUTHENTICATED_USER}) - @Override - public SourceDefinitionRead getSourceDefinition(final SourceDefinitionIdRequestBody sourceDefinitionIdRequestBody) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.getSourceDefinition(sourceDefinitionIdRequestBody)); - } - - @Post("/get_for_workspace") - @Secured({READER}) - @SecuredWorkspace - @Override - public SourceDefinitionRead getSourceDefinitionForWorkspace(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.getSourceDefinitionForWorkspace(sourceDefinitionIdWithWorkspaceId)); - } - - @Post("/grant_definition") - @Secured({ADMIN}) - @Override - public PrivateSourceDefinitionRead grantSourceDefinitionToWorkspace(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.grantSourceDefinitionToWorkspace(sourceDefinitionIdWithWorkspaceId)); - } - - @Post("/list_latest") - @Secured({AUTHENTICATED_USER}) - @Override - public SourceDefinitionReadList listLatestSourceDefinitions() { - return ApiHelper.execute(sourceDefinitionsHandler::listLatestSourceDefinitions); - } - - @Post("/list_private") - @Secured({ADMIN}) - @Override - public PrivateSourceDefinitionReadList listPrivateSourceDefinitions(final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.listPrivateSourceDefinitions(workspaceIdRequestBody)); - } - - @Post("/list") - @Secured({AUTHENTICATED_USER}) - @Override - public SourceDefinitionReadList listSourceDefinitions() { - return ApiHelper.execute(sourceDefinitionsHandler::listSourceDefinitions); - } - - @Post("/list_for_workspace") - @Secured({READER}) - @SecuredWorkspace - @Override - public SourceDefinitionReadList listSourceDefinitionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.listSourceDefinitionsForWorkspace(workspaceIdRequestBody)); - } - - @Post("/revoke_definition") - @Secured({ADMIN}) - @Override - @Status(HttpStatus.NO_CONTENT) - public void revokeSourceDefinitionFromWorkspace(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) { - ApiHelper.execute(() -> { - sourceDefinitionsHandler.revokeSourceDefinitionFromWorkspace(sourceDefinitionIdWithWorkspaceId); - return null; - }); - } - - @Post("/update") - @Secured({AUTHENTICATED_USER}) - @Override - public SourceDefinitionRead updateSourceDefinition(final SourceDefinitionUpdate sourceDefinitionUpdate) { - return ApiHelper.execute(() -> sourceDefinitionsHandler.updateSourceDefinition(sourceDefinitionUpdate)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionSpecificationApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionSpecificationApiController.java deleted file mode 100644 index 0bf03a8fd4034..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceDefinitionSpecificationApiController.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; - -import io.airbyte.api.generated.SourceDefinitionSpecificationApi; -import io.airbyte.api.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.model.generated.SourceDefinitionSpecificationRead; -import io.airbyte.commons.server.handlers.SchedulerHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/source_definition_specifications") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class SourceDefinitionSpecificationApiController implements SourceDefinitionSpecificationApi { - - private final SchedulerHandler schedulerHandler; - - public SourceDefinitionSpecificationApiController(final SchedulerHandler schedulerHandler) { - this.schedulerHandler = schedulerHandler; - } - - @Post("/get") - @Secured({AUTHENTICATED_USER}) - @Override - public SourceDefinitionSpecificationRead getSourceDefinitionSpecification(final SourceDefinitionIdWithWorkspaceId sourceDefinitionIdWithWorkspaceId) { - return ApiHelper.execute(() -> schedulerHandler.getSourceDefinitionSpecification(sourceDefinitionIdWithWorkspaceId)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceOauthApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/SourceOauthApiController.java deleted file mode 100644 index 14f0069e260ab..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/SourceOauthApiController.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; - -import io.airbyte.api.generated.SourceOauthApi; -import io.airbyte.api.model.generated.CompleteSourceOauthRequest; -import io.airbyte.api.model.generated.OAuthConsentRead; -import io.airbyte.api.model.generated.SetInstancewideSourceOauthParamsRequestBody; -import io.airbyte.api.model.generated.SourceOauthConsentRequest; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.OAuthHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; -import java.util.Map; - -@Controller("/api/v1/source_oauths") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class SourceOauthApiController implements SourceOauthApi { - - private final OAuthHandler oAuthHandler; - - public SourceOauthApiController(final OAuthHandler oAuthHandler) { - this.oAuthHandler = oAuthHandler; - } - - @Post("/complete_oauth") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public Map completeSourceOAuth(@Body final CompleteSourceOauthRequest completeSourceOauthRequest) { - return ApiHelper.execute(() -> oAuthHandler.completeSourceOAuth(completeSourceOauthRequest)); - } - - @Post("/get_consent_url") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public OAuthConsentRead getSourceOAuthConsent(@Body final SourceOauthConsentRequest sourceOauthConsentRequest) { - return ApiHelper.execute(() -> oAuthHandler.getSourceOAuthConsent(sourceOauthConsentRequest)); - } - - @Post("/oauth_params/create") - @Secured({ADMIN}) - @Override - public void setInstancewideSourceOauthParams(@Body final SetInstancewideSourceOauthParamsRequestBody setInstancewideSourceOauthParamsRequestBody) { - ApiHelper.execute(() -> { - oAuthHandler.setSourceInstancewideOauthParams(setInstancewideSourceOauthParamsRequestBody); - return null; - }); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/StateApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/StateApiController.java deleted file mode 100644 index 7446ca7f15af9..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/StateApiController.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.ADMIN; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.StateApi; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionState; -import io.airbyte.api.model.generated.ConnectionStateCreateOrUpdate; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.StateHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/state") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class StateApiController implements StateApi { - - private final StateHandler stateHandler; - - public StateApiController(final StateHandler stateHandler) { - this.stateHandler = stateHandler; - } - - @Post("/create_or_update") - @Secured({ADMIN}) - @Override - public ConnectionState createOrUpdateState(final ConnectionStateCreateOrUpdate connectionStateCreateOrUpdate) { - return ApiHelper.execute(() -> stateHandler.createOrUpdateState(connectionStateCreateOrUpdate)); - } - - @Post("/get") - @Secured({READER}) - @SecuredWorkspace - @Override - public ConnectionState getState(final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> stateHandler.getState(connectionIdRequestBody)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/WebBackendApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/WebBackendApiController.java deleted file mode 100644 index ca42ae51e2cb3..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/WebBackendApiController.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; -import static io.airbyte.commons.auth.AuthRoleConstants.EDITOR; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.WebBackendApi; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.ConnectionStateType; -import io.airbyte.api.model.generated.WebBackendCheckUpdatesRead; -import io.airbyte.api.model.generated.WebBackendConnectionCreate; -import io.airbyte.api.model.generated.WebBackendConnectionListRequestBody; -import io.airbyte.api.model.generated.WebBackendConnectionRead; -import io.airbyte.api.model.generated.WebBackendConnectionReadList; -import io.airbyte.api.model.generated.WebBackendConnectionRequestBody; -import io.airbyte.api.model.generated.WebBackendConnectionUpdate; -import io.airbyte.api.model.generated.WebBackendGeographiesListResult; -import io.airbyte.api.model.generated.WebBackendWorkspaceState; -import io.airbyte.api.model.generated.WebBackendWorkspaceStateResult; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.WebBackendCheckUpdatesHandler; -import io.airbyte.commons.server.handlers.WebBackendConnectionsHandler; -import io.airbyte.commons.server.handlers.WebBackendGeographiesHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/web_backend") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -public class WebBackendApiController implements WebBackendApi { - - private final WebBackendConnectionsHandler webBackendConnectionsHandler; - private final WebBackendGeographiesHandler webBackendGeographiesHandler; - private final WebBackendCheckUpdatesHandler webBackendCheckUpdatesHandler; - - public WebBackendApiController(final WebBackendConnectionsHandler webBackendConnectionsHandler, - final WebBackendGeographiesHandler webBackendGeographiesHandler, - final WebBackendCheckUpdatesHandler webBackendCheckUpdatesHandler) { - this.webBackendConnectionsHandler = webBackendConnectionsHandler; - this.webBackendGeographiesHandler = webBackendGeographiesHandler; - this.webBackendCheckUpdatesHandler = webBackendCheckUpdatesHandler; - } - - @Post("/state/get_type") - @Secured({READER}) - @SecuredWorkspace - @Override - public ConnectionStateType getStateType(final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> webBackendConnectionsHandler.getStateType(connectionIdRequestBody)); - } - - @Post("/check_updates") - @Secured({READER}) - @Override - public WebBackendCheckUpdatesRead webBackendCheckUpdates() { - return ApiHelper.execute(webBackendCheckUpdatesHandler::checkUpdates); - } - - @Post("/connections/create") - @Secured({EDITOR}) - @SecuredWorkspace - @Override - public WebBackendConnectionRead webBackendCreateConnection(final WebBackendConnectionCreate webBackendConnectionCreate) { - return ApiHelper.execute(() -> webBackendConnectionsHandler.webBackendCreateConnection(webBackendConnectionCreate)); - } - - @Post("/connections/get") - @Secured({READER}) - @SecuredWorkspace - @Override - public WebBackendConnectionRead webBackendGetConnection(final WebBackendConnectionRequestBody webBackendConnectionRequestBody) { - return ApiHelper.execute(() -> webBackendConnectionsHandler.webBackendGetConnection(webBackendConnectionRequestBody)); - } - - @Post("/workspace/state") - @Secured({READER}) - @SecuredWorkspace - @Override - public WebBackendWorkspaceStateResult webBackendGetWorkspaceState(final WebBackendWorkspaceState webBackendWorkspaceState) { - return ApiHelper.execute(() -> webBackendConnectionsHandler.getWorkspaceState(webBackendWorkspaceState)); - } - - @Post("/connections/list") - @Secured({READER}) - @SecuredWorkspace - @Override - public WebBackendConnectionReadList webBackendListConnectionsForWorkspace(final WebBackendConnectionListRequestBody webBackendConnectionListRequestBody) { - return ApiHelper.execute(() -> webBackendConnectionsHandler.webBackendListConnectionsForWorkspace(webBackendConnectionListRequestBody)); - } - - @Post("/geographies/list") - @Secured({AUTHENTICATED_USER}) - @Override - public WebBackendGeographiesListResult webBackendListGeographies() { - return ApiHelper.execute(webBackendGeographiesHandler::listGeographiesOSS); - } - - @Post("/connections/update") - @Secured({EDITOR}) - @Override - public WebBackendConnectionRead webBackendUpdateConnection(final WebBackendConnectionUpdate webBackendConnectionUpdate) { - return ApiHelper.execute(() -> webBackendConnectionsHandler.webBackendUpdateConnection(webBackendConnectionUpdate)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/apis/WorkspaceApiController.java b/airbyte-server/src/main/java/io/airbyte/server/apis/WorkspaceApiController.java deleted file mode 100644 index 1611a7807871a..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/apis/WorkspaceApiController.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static io.airbyte.commons.auth.AuthRoleConstants.AUTHENTICATED_USER; -import static io.airbyte.commons.auth.AuthRoleConstants.OWNER; -import static io.airbyte.commons.auth.AuthRoleConstants.READER; - -import io.airbyte.api.generated.WorkspaceApi; -import io.airbyte.api.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.model.generated.SlugRequestBody; -import io.airbyte.api.model.generated.WorkspaceCreate; -import io.airbyte.api.model.generated.WorkspaceGiveFeedback; -import io.airbyte.api.model.generated.WorkspaceIdRequestBody; -import io.airbyte.api.model.generated.WorkspaceRead; -import io.airbyte.api.model.generated.WorkspaceReadList; -import io.airbyte.api.model.generated.WorkspaceUpdate; -import io.airbyte.api.model.generated.WorkspaceUpdateName; -import io.airbyte.commons.auth.SecuredWorkspace; -import io.airbyte.commons.server.handlers.WorkspacesHandler; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.annotation.Body; -import io.micronaut.http.annotation.Controller; -import io.micronaut.http.annotation.Post; -import io.micronaut.http.annotation.Status; -import io.micronaut.security.annotation.Secured; -import io.micronaut.security.rules.SecurityRule; - -@Controller("/api/v1/workspaces") -@Requires(property = "airbyte.deployment-mode", - value = "OSS") -@Secured(SecurityRule.IS_AUTHENTICATED) -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class WorkspaceApiController implements WorkspaceApi { - - private final WorkspacesHandler workspacesHandler; - - public WorkspaceApiController(final WorkspacesHandler workspacesHandler) { - this.workspacesHandler = workspacesHandler; - } - - @Post("/create") - @Secured({AUTHENTICATED_USER}) - @Override - public WorkspaceRead createWorkspace(@Body final WorkspaceCreate workspaceCreate) { - return ApiHelper.execute(() -> workspacesHandler.createWorkspace(workspaceCreate)); - } - - @Post("/delete") - @Secured({OWNER}) - @SecuredWorkspace - @Override - @Status(HttpStatus.NO_CONTENT) - public void deleteWorkspace(@Body final WorkspaceIdRequestBody workspaceIdRequestBody) { - ApiHelper.execute(() -> { - workspacesHandler.deleteWorkspace(workspaceIdRequestBody); - return null; - }); - } - - @Post("/get") - @Secured({OWNER}) - @SecuredWorkspace - @Override - public WorkspaceRead getWorkspace(@Body final WorkspaceIdRequestBody workspaceIdRequestBody) { - return ApiHelper.execute(() -> workspacesHandler.getWorkspace(workspaceIdRequestBody)); - } - - @Post("/get_by_slug") - @Secured({OWNER}) - @SecuredWorkspace - @Override - public WorkspaceRead getWorkspaceBySlug(@Body final SlugRequestBody slugRequestBody) { - return ApiHelper.execute(() -> workspacesHandler.getWorkspaceBySlug(slugRequestBody)); - } - - @Post("/list") - @Secured({AUTHENTICATED_USER}) - @Override - public WorkspaceReadList listWorkspaces() { - return ApiHelper.execute(workspacesHandler::listWorkspaces); - } - - @Post("/update") - @Secured({OWNER}) - @SecuredWorkspace - @Override - public WorkspaceRead updateWorkspace(@Body final WorkspaceUpdate workspaceUpdate) { - return ApiHelper.execute(() -> workspacesHandler.updateWorkspace(workspaceUpdate)); - } - - @Post("/tag_feedback_status_as_done") - @Secured({OWNER}) - @SecuredWorkspace - @Override - public void updateWorkspaceFeedback(@Body final WorkspaceGiveFeedback workspaceGiveFeedback) { - ApiHelper.execute(() -> { - workspacesHandler.setFeedbackDone(workspaceGiveFeedback); - return null; - }); - } - - @Post("/update_name") - @Secured({OWNER}) - @SecuredWorkspace - @Override - public WorkspaceRead updateWorkspaceName(@Body final WorkspaceUpdateName workspaceUpdateName) { - return ApiHelper.execute(() -> workspacesHandler.updateWorkspaceName(workspaceUpdateName)); - } - - @Post("/get_by_connection_id") - @Secured({READER}) - @Override - public WorkspaceRead getWorkspaceByConnectionId(@Body final ConnectionIdRequestBody connectionIdRequestBody) { - return ApiHelper.execute(() -> workspacesHandler.getWorkspaceByConnectionId(connectionIdRequestBody)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/ApplicationBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/ApplicationBeanFactory.java deleted file mode 100644 index e70d08d72da5b..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/ApplicationBeanFactory.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.analytics.TrackingClient; -import io.airbyte.commons.features.EnvVariableFeatureFlags; -import io.airbyte.commons.features.FeatureFlags; -import io.airbyte.commons.server.scheduler.EventRunner; -import io.airbyte.commons.server.scheduler.TemporalEventRunner; -import io.airbyte.commons.server.services.AirbyteGithubStore; -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.version.AirbyteProtocolVersionRange; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.commons.version.Version; -import io.airbyte.config.Configs.DeploymentMode; -import io.airbyte.config.Configs.TrackingStrategy; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.split_secrets.JsonSecretsProcessor; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.WebUrlHelper; -import io.airbyte.persistence.job.tracker.JobTracker; -import io.airbyte.validation.json.JsonSchemaValidator; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import io.micronaut.core.util.StringUtils; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.nio.file.Path; -import java.util.Locale; -import java.util.UUID; -import java.util.function.Function; -import java.util.function.Supplier; - -@Factory -public class ApplicationBeanFactory { - - @Singleton - public Supplier randomUUIDSupplier() { - return () -> UUID.randomUUID(); - } - - @Singleton - public EventRunner eventRunner(final TemporalClient temporalClient) { - return new TemporalEventRunner(temporalClient); - } - - @Singleton - public TrackingStrategy trackingStrategy(@Value("${airbyte.tracking-strategy}") final String trackingStrategy) { - return convertToEnum(trackingStrategy, TrackingStrategy::valueOf, TrackingStrategy.LOGGING); - } - - @Singleton - public AirbyteVersion airbyteVersion(@Value("${airbyte.version}") final String airbyteVersion) { - return new AirbyteVersion(airbyteVersion); - } - - @Singleton - public DeploymentMode deploymentMode(@Value("${airbyte.deployment-mode}") final String deploymentMode) { - return convertToEnum(deploymentMode, DeploymentMode::valueOf, DeploymentMode.OSS); - } - - @Singleton - public JobTracker jobTracker( - final ConfigRepository configRepository, - final JobPersistence jobPersistence, - final TrackingClient trackingClient) { - return new JobTracker(configRepository, jobPersistence, trackingClient); - } - - @Singleton - public WebUrlHelper webUrlHelper(@Value("${airbyte.web-app.url}") final String webAppUrl) { - return new WebUrlHelper(webAppUrl); - } - - @Singleton - public FeatureFlags featureFlags() { - return new EnvVariableFeatureFlags(); - } - - @Singleton - @Named("workspaceRoot") - public Path workspaceRoot(@Value("${airbyte.workspace.root}") final String workspaceRoot) { - return Path.of(workspaceRoot); - } - - @Singleton - public JsonSecretsProcessor jsonSecretsProcessor(final FeatureFlags featureFlags) { - return JsonSecretsProcessor.builder() - .copySecrets(false) - .build(); - } - - @Singleton - public JsonSchemaValidator jsonSchemaValidator() { - return new JsonSchemaValidator(); - } - - @Singleton - public AirbyteGithubStore airbyteGithubStore() { - return AirbyteGithubStore.production(); - } - - @Singleton - public AirbyteProtocolVersionRange airbyteProtocolVersionRange( - @Value("${airbyte.protocol.min-version}") final String minVersion, - @Value("${airbyte.protocol.max-version}") final String maxVersion) { - return new AirbyteProtocolVersionRange(new Version(minVersion), new Version(maxVersion)); - } - - private T convertToEnum(final String value, final Function creatorFunction, final T defaultValue) { - return StringUtils.isNotEmpty(value) ? creatorFunction.apply(value.toUpperCase(Locale.ROOT)) : defaultValue; - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/CloudStorageBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/CloudStorageBeanFactory.java deleted file mode 100644 index e914b815a0895..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/CloudStorageBeanFactory.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.config.storage.CloudStorageConfigs; -import io.airbyte.config.storage.CloudStorageConfigs.GcsConfig; -import io.airbyte.config.storage.CloudStorageConfigs.MinioConfig; -import io.airbyte.config.storage.CloudStorageConfigs.S3Config; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Named; -import jakarta.inject.Singleton; - -/** - * Micronaut bean factory for cloud storage-related singletons. - */ -@Factory -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class CloudStorageBeanFactory { - - @Singleton - @Requires(property = "airbyte.cloud.storage.logs.type", - pattern = "(?i)^gcs$") - @Named("logStorageConfigs") - public CloudStorageConfigs gcsLogStorageConfigs( - @Value("${airbyte.cloud.storage.logs.gcs.bucket}") final String gcsLogBucket, - @Value("${airbyte.cloud.storage.logs.gcs.application-credentials}") final String googleApplicationCredentials) { - return CloudStorageConfigs.gcs(new GcsConfig(gcsLogBucket, googleApplicationCredentials)); - } - - @Singleton - @Requires(property = "airbyte.cloud.storage.logs.type", - pattern = "(?i)^minio$") - @Named("logStorageConfigs") - public CloudStorageConfigs minioLogStorageConfigs( - @Value("${airbyte.cloud.storage.logs.minio.access-key}") final String awsAccessKeyId, - @Value("${airbyte.cloud.storage.logs.minio.secret-access-key}") final String awsSecretAccessKey, - @Value("${airbyte.cloud.storage.logs.minio.bucket}") final String s3LogBucket, - @Value("${airbyte.cloud.storage.logs.minio.endpoint}") final String s3MinioEndpoint) { - return CloudStorageConfigs.minio(new MinioConfig(s3LogBucket, awsAccessKeyId, awsSecretAccessKey, s3MinioEndpoint)); - } - - @Singleton - @Requires(property = "airbyte.cloud.storage.logs.type", - pattern = "(?i)^s3$") - @Named("logStorageConfigs") - public CloudStorageConfigs s3LogStorageConfigs( - @Value("${airbyte.cloud.storage.logs.s3.access-key}") final String awsAccessKeyId, - @Value("${airbyte.cloud.storage.logs.s3.secret-access-key}") final String awsSecretAccessKey, - @Value("${airbyte.cloud.storage.logs.s3.bucket}") final String s3LogBucket, - @Value("${airbyte.cloud.storage.logs.s3.region}") final String s3LogBucketRegion) { - return CloudStorageConfigs.s3(new S3Config(s3LogBucket, awsAccessKeyId, awsSecretAccessKey, s3LogBucketRegion)); - } - - @Singleton - @Requires(property = "airbyte.cloud.storage.state.type", - pattern = "(?i)^gcs$") - @Named("stateStorageConfigs") - public CloudStorageConfigs gcsStateStorageConfiguration( - @Value("${airbyte.cloud.storage.state.gcs.bucket}") final String gcsBucketName, - @Value("${airbyte.cloud.storage.state.gcs.application-credentials}") final String gcsApplicationCredentials) { - return CloudStorageConfigs.gcs(new GcsConfig(gcsBucketName, gcsApplicationCredentials)); - } - - @Singleton - @Requires(property = "airbyte.cloud.storage.state.type", - pattern = "(?i)^minio$") - @Named("stateStorageConfigs") - public CloudStorageConfigs minioStateStorageConfiguration( - @Value("${airbyte.cloud.storage.state.minio.bucket}") final String bucketName, - @Value("${airbyte.cloud.storage.state.minio.access-key}") final String awsAccessKey, - @Value("${airbyte.cloud.storage.state.minio.secret-access-key}") final String secretAccessKey, - @Value("${airbyte.cloud.storage.state.minio.endpoint}") final String endpoint) { - return CloudStorageConfigs.minio(new MinioConfig(bucketName, awsAccessKey, secretAccessKey, endpoint)); - } - - @Singleton - @Requires(property = "airbyte.cloud.storage.state.type", - pattern = "(?i)^s3$") - @Named("stateStorageConfigs") - public CloudStorageConfigs s3StateStorageConfiguration( - @Value("${airbyte.cloud.storage.state.s3.bucket}") final String bucketName, - @Value("${airbyte.cloud.storage.state.s3.access-key}") final String awsAccessKey, - @Value("${airbyte.cloud.storage.state.s3.secret-access-key}") final String secretAcessKey, - @Value("${airbyte.cloud.storage.state.s3.region}") final String s3Region) { - return CloudStorageConfigs.s3(new S3Config(bucketName, awsAccessKey, secretAcessKey, s3Region)); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/DatabaseBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/DatabaseBeanFactory.java deleted file mode 100644 index 326ef184562d5..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/DatabaseBeanFactory.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.StatePersistence; -import io.airbyte.config.persistence.StreamResetPersistence; -import io.airbyte.db.Database; -import io.airbyte.db.check.DatabaseMigrationCheck; -import io.airbyte.db.check.impl.JobsDatabaseAvailabilityCheck; -import io.airbyte.db.factory.DatabaseCheckFactory; -import io.airbyte.db.instance.DatabaseConstants; -import io.airbyte.persistence.job.DefaultJobPersistence; -import io.airbyte.persistence.job.JobPersistence; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import io.micronaut.flyway.FlywayConfigurationProperties; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.io.IOException; -import javax.sql.DataSource; -import lombok.extern.slf4j.Slf4j; -import org.flywaydb.core.Flyway; -import org.jooq.DSLContext; - -/** - * Micronaut bean factory for database-related singletons. - */ -@Factory -@Slf4j -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class DatabaseBeanFactory { - - private static final String BASELINE_DESCRIPTION = "Baseline from file-based migration v1"; - private static final Boolean BASELINE_ON_MIGRATION = true; - private static final String INSTALLED_BY = "ServerApp"; - - @Singleton - @Named("configDatabase") - public Database configDatabase(@Named("config") final DSLContext dslContext) throws IOException { - return new Database(dslContext); - } - - @Singleton - @Named("configFlyway") - public Flyway configFlyway(@Named("config") final FlywayConfigurationProperties configFlywayConfigurationProperties, - @Named("config") final DataSource configDataSource, - @Value("${airbyte.flyway.configs.minimum-migration-version}") final String baselineVersion) { - return configFlywayConfigurationProperties.getFluentConfiguration() - .dataSource(configDataSource) - .baselineVersion(baselineVersion) - .baselineDescription(BASELINE_DESCRIPTION) - .baselineOnMigrate(BASELINE_ON_MIGRATION) - .installedBy(INSTALLED_BY) - .table(String.format("airbyte_%s_migrations", "configs")) - .load(); - } - - @Singleton - @Named("jobsFlyway") - public Flyway jobsFlyway(@Named("jobs") final FlywayConfigurationProperties jobsFlywayConfigurationProperties, - @Named("config") final DataSource jobsDataSource, - @Value("${airbyte.flyway.jobs.minimum-migration-version}") final String baselineVersion) { - return jobsFlywayConfigurationProperties.getFluentConfiguration() - .dataSource(jobsDataSource) - .baselineVersion(baselineVersion) - .baselineDescription(BASELINE_DESCRIPTION) - .baselineOnMigrate(BASELINE_ON_MIGRATION) - .installedBy(INSTALLED_BY) - .table(String.format("airbyte_%s_migrations", "jobs")) - .load(); - } - - @Singleton - public ConfigRepository configRepository(@Named("configDatabase") final Database configDatabase) { - return new ConfigRepository(configDatabase); - } - - @Singleton - public JobPersistence jobPersistence(@Named("configDatabase") final Database jobDatabase) { - return new DefaultJobPersistence(jobDatabase); - } - - @Singleton - public StatePersistence statePersistence(@Named("configDatabase") final Database configDatabase) { - return new StatePersistence(configDatabase); - } - - @Singleton - @Named("configsDatabaseMigrationCheck") - public DatabaseMigrationCheck configsDatabaseMigrationCheck(@Named("config") final DSLContext dslContext, - @Named("configFlyway") final Flyway configsFlyway, - @Value("${airbyte.flyway.configs.minimum-migration-version}") final String configsDatabaseMinimumFlywayMigrationVersion, - @Value("${airbyte.flyway.configs.initialization-timeout-ms}") final Long configsDatabaseInitializationTimeoutMs) { - log.info("Configs database configuration: {} {}", configsDatabaseMinimumFlywayMigrationVersion, configsDatabaseInitializationTimeoutMs); - return DatabaseCheckFactory - .createConfigsDatabaseMigrationCheck(dslContext, configsFlyway, configsDatabaseMinimumFlywayMigrationVersion, - configsDatabaseInitializationTimeoutMs); - } - - @Singleton - @Named("jobsDatabaseMigrationCheck") - public DatabaseMigrationCheck jobsDatabaseMigrationCheck(@Named("config") final DSLContext dslContext, - @Named("jobsFlyway") final Flyway jobsFlyway, - @Value("${airbyte.flyway.jobs.minimum-migration-version}") final String jobsDatabaseMinimumFlywayMigrationVersion, - @Value("${airbyte.flyway.jobs.initialization-timeout-ms}") final Long jobsDatabaseInitializationTimeoutMs) { - return DatabaseCheckFactory - .createJobsDatabaseMigrationCheck(dslContext, jobsFlyway, jobsDatabaseMinimumFlywayMigrationVersion, - jobsDatabaseInitializationTimeoutMs); - } - - @Singleton - @Named("jobsDatabaseAvailabilityCheck") - public JobsDatabaseAvailabilityCheck jobsDatabaseAvailabilityCheck(@Named("config") final DSLContext dslContext) { - return new JobsDatabaseAvailabilityCheck(dslContext, DatabaseConstants.DEFAULT_ASSERT_DATABASE_TIMEOUT_MS); - } - - @Singleton - public StreamResetPersistence streamResetPersistence(@Named("configDatabase") final Database configDatabase) { - return new StreamResetPersistence(configDatabase); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/HelperBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/HelperBeanFactory.java deleted file mode 100644 index d5493f2a69394..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/HelperBeanFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.WorkspaceHelper; -import io.micronaut.context.annotation.Factory; -import jakarta.inject.Singleton; - -@Factory -public class HelperBeanFactory { - - @Singleton - public WorkspaceHelper workspaceHelper(final ConfigRepository configRepository, final JobPersistence jobPersistence) { - return new WorkspaceHelper(configRepository, jobPersistence); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/JobErrorReportingBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/JobErrorReportingBeanFactory.java deleted file mode 100644 index a02f36a90339f..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/JobErrorReportingBeanFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.config.Configs.DeploymentMode; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.WebUrlHelper; -import io.airbyte.persistence.job.errorreporter.JobErrorReporter; -import io.airbyte.persistence.job.errorreporter.JobErrorReportingClient; -import io.airbyte.persistence.job.errorreporter.LoggingJobErrorReportingClient; -import io.airbyte.persistence.job.errorreporter.SentryExceptionHelper; -import io.airbyte.persistence.job.errorreporter.SentryJobErrorReportingClient; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.util.Optional; - -/** - * Micronaut bean factory for job error reporting-related singletons. - */ -@Factory -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class JobErrorReportingBeanFactory { - - @Singleton - @Requires(property = "airbyte.worker.job.error-reporting.strategy", - pattern = "(?i)^sentry$") - @Named("jobErrorReportingClient") - public JobErrorReportingClient sentryJobErrorReportingClient( - @Value("${airbyte.worker.job.error-reporting.sentry.dsn}") final String sentryDsn) { - return new SentryJobErrorReportingClient(sentryDsn, new SentryExceptionHelper()); - } - - @Singleton - @Requires(property = "airbyte.worker.job.error-reporting.strategy", - pattern = "(?i)^logging$") - @Named("jobErrorReportingClient") - public JobErrorReportingClient loggingJobErrorReportingClient() { - return new LoggingJobErrorReportingClient(); - } - - @Singleton - public JobErrorReporter jobErrorReporter( - @Value("${airbyte.version}") final String airbyteVersion, - final ConfigRepository configRepository, - final DeploymentMode deploymentMode, - @Named("jobErrorReportingClient") final Optional jobErrorReportingClient, - final WebUrlHelper webUrlHelper) { - return new JobErrorReporter( - configRepository, - deploymentMode, - airbyteVersion, - webUrlHelper, - jobErrorReportingClient.orElseGet(() -> new LoggingJobErrorReportingClient())); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/SecretPersistenceBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/SecretPersistenceBeanFactory.java deleted file mode 100644 index ce96b37dbce07..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/SecretPersistenceBeanFactory.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.config.persistence.SecretsRepositoryReader; -import io.airbyte.config.persistence.SecretsRepositoryWriter; -import io.airbyte.config.persistence.split_secrets.AWSSecretManagerPersistence; -import io.airbyte.config.persistence.split_secrets.GoogleSecretManagerPersistence; -import io.airbyte.config.persistence.split_secrets.LocalTestingSecretPersistence; -import io.airbyte.config.persistence.split_secrets.RealSecretsHydrator; -import io.airbyte.config.persistence.split_secrets.SecretPersistence; -import io.airbyte.config.persistence.split_secrets.SecretsHydrator; -import io.airbyte.config.persistence.split_secrets.VaultSecretPersistence; -import io.airbyte.db.Database; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Requires; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Named; -import jakarta.inject.Singleton; -import java.util.Optional; - -/** - * Micronaut bean factory for secret persistence-related singletons. - */ -@Factory -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public class SecretPersistenceBeanFactory { - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!testing_config_db_table).*") - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!google_secret_manager).*") - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!vault).*") - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^(?!aws_secret_manager).*") - @Named("secretPersistence") - public SecretPersistence defaultSecretPersistence(@Named("configDatabase") final Database configDatabase) { - return localTestingSecretPersistence(configDatabase); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^testing_config_db_table$") - @Named("secretPersistence") - public SecretPersistence localTestingSecretPersistence(@Named("configDatabase") final Database configDatabase) { - return new LocalTestingSecretPersistence(configDatabase); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^testing_config_db_table$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralLocalTestingSecretPersistence(@Named("configDatabase") final Database configDatabase) { - return new LocalTestingSecretPersistence(configDatabase); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^google_secret_manager$") - @Named("secretPersistence") - public SecretPersistence googleSecretPersistence(@Value("${airbyte.secret.store.gcp.credentials}") final String credentials, - @Value("${airbyte.secret.store.gcp.project-id}") final String projectId) { - return GoogleSecretManagerPersistence.getLongLived(projectId, credentials); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^google_secret_manager$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralGoogleSecretPersistence(@Value("${airbyte.secret.store.gcp.credentials}") final String credentials, - @Value("${airbyte.secret.store.gcp.project-id}") final String projectId) { - return GoogleSecretManagerPersistence.getEphemeral(projectId, credentials); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^vault$") - @Named("secretPersistence") - public SecretPersistence vaultSecretPersistence(@Value("${airbyte.secret.store.vault.address}") final String address, - @Value("${airbyte.secret.store.vault.prefix}") final String prefix, - @Value("${airbyte.secret.store.vault.token}") final String token) { - return new VaultSecretPersistence(address, prefix, token); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^vault$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralVaultSecretPersistence(@Value("${airbyte.secret.store.vault.address}") final String address, - @Value("${airbyte.secret.store.vault.prefix}") final String prefix, - @Value("${airbyte.secret.store.vault.token}") final String token) { - return new VaultSecretPersistence(address, prefix, token); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^aws_secret_manager$") - @Named("secretPersistence") - public SecretPersistence awsSecretPersistence(@Value("${airbyte.secret.store.aws.access-key}") final String awsAccessKey, - @Value("${airbyte.secret.store.aws.secret-key}") final String awsSecretKey) { - return new AWSSecretManagerPersistence(awsAccessKey, awsSecretKey); - } - - @Singleton - @Requires(property = "airbyte.secret.persistence", - pattern = "(?i)^aws_secret_manager$") - @Named("ephemeralSecretPersistence") - public SecretPersistence ephemeralAwsSecretPersistence(@Value("${airbyte.secret.store.aws.access-key}") final String awsAccessKey, - @Value("${airbyte.secret.store.aws.secret-key}") final String awsSecretKey) { - return new AWSSecretManagerPersistence(awsAccessKey, awsSecretKey); - } - - @Singleton - public SecretsHydrator secretsHydrator(@Named("secretPersistence") final SecretPersistence secretPersistence) { - return new RealSecretsHydrator(secretPersistence); - } - - @Singleton - public SecretsRepositoryReader secretsRepositoryReader(final ConfigRepository configRepository, final SecretsHydrator secretsHydrator) { - return new SecretsRepositoryReader(configRepository, secretsHydrator); - } - - @Singleton - public SecretsRepositoryWriter secretsRepositoryWriter(final ConfigRepository configRepository, - @Named("secretPersistence") final Optional secretPersistence, - @Named("ephemeralSecretPersistence") final Optional ephemeralSecretPersistence) { - return new SecretsRepositoryWriter(configRepository, secretPersistence, ephemeralSecretPersistence); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/config/TemporalBeanFactory.java b/airbyte-server/src/main/java/io/airbyte/server/config/TemporalBeanFactory.java deleted file mode 100644 index 5e7565b74d212..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/config/TemporalBeanFactory.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.config; - -import io.airbyte.analytics.Deployment; -import io.airbyte.analytics.TrackingClient; -import io.airbyte.analytics.TrackingClientSingleton; -import io.airbyte.commons.server.scheduler.DefaultSynchronousSchedulerClient; -import io.airbyte.commons.server.scheduler.SynchronousSchedulerClient; -import io.airbyte.commons.temporal.TemporalClient; -import io.airbyte.commons.temporal.scheduling.DefaultTaskQueueMapper; -import io.airbyte.commons.temporal.scheduling.RouterService; -import io.airbyte.commons.temporal.scheduling.TaskQueueMapper; -import io.airbyte.commons.version.AirbyteVersion; -import io.airbyte.config.Configs.DeploymentMode; -import io.airbyte.config.Configs.TrackingStrategy; -import io.airbyte.config.Configs.WorkerEnvironment; -import io.airbyte.config.persistence.ConfigRepository; -import io.airbyte.persistence.job.JobPersistence; -import io.airbyte.persistence.job.errorreporter.JobErrorReporter; -import io.airbyte.persistence.job.factory.OAuthConfigSupplier; -import io.airbyte.persistence.job.tracker.JobTracker; -import io.micronaut.context.annotation.Factory; -import io.micronaut.context.annotation.Value; -import jakarta.inject.Singleton; -import java.io.IOException; - -/** - * Micronaut bean factory for Temporal-related singletons. - */ -@Factory -public class TemporalBeanFactory { - - @Singleton - public TrackingClient trackingClient(final TrackingStrategy trackingStrategy, - final DeploymentMode deploymentMode, - final JobPersistence jobPersistence, - final WorkerEnvironment workerEnvironment, - @Value("${airbyte.role}") final String airbyteRole, - final AirbyteVersion airbyteVersion, - final ConfigRepository configRepository) - throws IOException { - - TrackingClientSingleton.initialize( - trackingStrategy, - new Deployment(deploymentMode, jobPersistence.getDeployment().orElseThrow(), - workerEnvironment), - airbyteRole, - airbyteVersion, - configRepository); - - return TrackingClientSingleton.get(); - } - - @Singleton - public OAuthConfigSupplier oAuthConfigSupplier(final ConfigRepository configRepository, final TrackingClient trackingClient) { - return new OAuthConfigSupplier(configRepository, trackingClient); - } - - @Singleton - public TaskQueueMapper taskQueueMapper() { - return new DefaultTaskQueueMapper(); - } - - @Singleton - public SynchronousSchedulerClient synchronousSchedulerClient(final TemporalClient temporalClient, - final JobTracker jobTracker, - final JobErrorReporter jobErrorReporter, - final OAuthConfigSupplier oAuthConfigSupplier, - final RouterService routerService) { - return new DefaultSynchronousSchedulerClient(temporalClient, jobTracker, jobErrorReporter, oAuthConfigSupplier, routerService); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidInputExceptionHandler.java b/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidInputExceptionHandler.java deleted file mode 100644 index 36b0dffbba5b8..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidInputExceptionHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.errors; - -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.errors.InvalidInputExceptionMapper; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; -import javax.validation.ConstraintViolationException; - -// https://www.baeldung.com/jersey-bean-validation#custom-exception-handler -// handles exceptions related to the request body not matching the openapi config. -@Produces -@Singleton -@Requires(classes = ConstraintViolationException.class) -public class InvalidInputExceptionHandler implements ExceptionHandler { - - @Override - public HttpResponse handle(final HttpRequest request, final ConstraintViolationException exception) { - return HttpResponse.status(HttpStatus.BAD_REQUEST) - .body(Jsons.serialize(InvalidInputExceptionMapper.infoFromConstraints(exception))) - .contentType(MediaType.APPLICATION_JSON_TYPE); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonExceptionHandler.java b/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonExceptionHandler.java deleted file mode 100644 index 4231f7777668e..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonExceptionHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.errors; - -import com.fasterxml.jackson.core.JsonParseException; -import io.airbyte.commons.server.errors.KnownException; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; - -@Produces -@Singleton -@Requires(classes = JsonParseException.class) -public class InvalidJsonExceptionHandler implements ExceptionHandler { - - @Override - public HttpResponse handle(final HttpRequest request, final JsonParseException exception) { - return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY) - .body( - KnownException.infoFromThrowableWithMessage(exception, "Invalid json. " + exception.getMessage() + " " + exception.getOriginalMessage())) - .contentType(MediaType.APPLICATION_JSON_TYPE); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonInputExceptionHandler.java b/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonInputExceptionHandler.java deleted file mode 100644 index 958a77bdb0843..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/errors/InvalidJsonInputExceptionHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.errors; - -import com.fasterxml.jackson.databind.JsonMappingException; -import io.airbyte.commons.server.errors.KnownException; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; - -@Produces -@Singleton -@Requires(classes = JsonMappingException.class) -public class InvalidJsonInputExceptionHandler implements ExceptionHandler { - - @Override - public HttpResponse handle(final HttpRequest request, final JsonMappingException exception) { - return HttpResponse.status(HttpStatus.UNPROCESSABLE_ENTITY) - .body(KnownException.infoFromThrowableWithMessage(exception, - "Invalid json input. " + exception.getMessage() + " " + exception.getOriginalMessage())) - .contentType(MediaType.APPLICATION_JSON_TYPE); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/errors/KnownExceptionHandler.java b/airbyte-server/src/main/java/io/airbyte/server/errors/KnownExceptionHandler.java deleted file mode 100644 index 6a3f420cc3595..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/errors/KnownExceptionHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.errors; - -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.server.errors.KnownException; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; - -@Produces -@Singleton -@Requires(classes = KnownException.class) -public class KnownExceptionHandler implements ExceptionHandler { - - @Override - public HttpResponse handle(HttpRequest request, KnownException exception) { - return HttpResponse.status(HttpStatus.valueOf(exception.getHttpCode())) - .body(Jsons.serialize(exception.getKnownExceptionInfo())) - .contentType(MediaType.APPLICATION_JSON_TYPE); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/errors/NotFoundExceptionHandler.java b/airbyte-server/src/main/java/io/airbyte/server/errors/NotFoundExceptionHandler.java deleted file mode 100644 index f4333d7906735..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/errors/NotFoundExceptionHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.errors; - -import io.airbyte.commons.server.errors.IdNotFoundKnownException; -import io.airbyte.commons.server.errors.KnownException; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; -import javax.ws.rs.NotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Produces -@Singleton -@Requires(classes = NotFoundException.class) -public class NotFoundExceptionHandler implements ExceptionHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(NotFoundExceptionHandler.class); - - @Override - public HttpResponse handle(final HttpRequest request, final NotFoundException exception) { - final IdNotFoundKnownException idnf = new IdNotFoundKnownException("Object not found. " + exception.getMessage(), exception); - LOGGER.error("Not found exception", idnf.getNotFoundKnownExceptionInfo()); - - return HttpResponse.status(HttpStatus.NOT_FOUND) - .body(KnownException.infoFromThrowableWithMessage(exception, "Internal Server Error: " + exception.getMessage())) - .contentType(MediaType.APPLICATION_JSON); - } - -} diff --git a/airbyte-server/src/main/java/io/airbyte/server/errors/UncaughtExceptionHandler.java b/airbyte-server/src/main/java/io/airbyte/server/errors/UncaughtExceptionHandler.java deleted file mode 100644 index 7441fe2dbaddd..0000000000000 --- a/airbyte-server/src/main/java/io/airbyte/server/errors/UncaughtExceptionHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.errors; - -import io.airbyte.commons.server.errors.KnownException; -import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; -import io.micronaut.http.HttpStatus; -import io.micronaut.http.MediaType; -import io.micronaut.http.annotation.Produces; -import io.micronaut.http.server.exceptions.ExceptionHandler; -import jakarta.inject.Singleton; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Produces -@Singleton -@Requires(classes = Throwable.class) -public class UncaughtExceptionHandler implements ExceptionHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(UncaughtExceptionHandler.class); - - @Override - public HttpResponse handle(final HttpRequest request, final Throwable exception) { - LOGGER.error("Uncaught exception", exception); - return HttpResponse.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(KnownException.infoFromThrowableWithMessage(exception, "Internal Server Error: " + exception.getMessage())) - .contentType(MediaType.APPLICATION_JSON); - } - -} diff --git a/airbyte-server/src/main/resources/application.yml b/airbyte-server/src/main/resources/application.yml deleted file mode 100644 index 7f22450b01c2d..0000000000000 --- a/airbyte-server/src/main/resources/application.yml +++ /dev/null @@ -1,162 +0,0 @@ -micronaut: - application: - name: airbyte-server - security: - authentication-provider-strategy: ALL - enabled: ${API_AUTHORIZATION_ENABLED:false} - server: - port: 8001 - cors: - enabled: true - configurations: - web: - allowedOrigins: - - ^.*$ -airbyte: - cloud: - storage: - logs: - type: ${WORKER_LOGS_STORAGE_TYPE:} - gcs: - application-credentials: ${GOOGLE_APPLICATION_CREDENTIALS:} - bucket: ${GCS_LOG_BUCKET:} - minio: - access-key: ${AWS_ACCESS_KEY_ID:} - bucket: ${S3_LOG_BUCKET:} - endpoint: ${S3_MINIO_ENDPOINT:} - secret-access-key: ${AWS_SECRET_ACCESS_KEY:} - s3: - access-key: ${AWS_ACCESS_KEY_ID:} - bucket: ${S3_LOG_BUCKET:} - region: ${S3_LOG_BUCKET_REGION:} - secret-access-key: ${AWS_SECRET_ACCESS_KEY:} - state: - type: ${WORKER_STATE_STORAGE_TYPE:} - gcs: - application-credentials: ${STATE_STORAGE_GCS_APPLICATION_CREDENTIALS:} - bucket: ${STATE_STORAGE_GCS_BUCKET_NAME:} - minio: - access-key: ${STATE_STORAGE_MINIO_ACCESS_KEY:} - bucket: ${STATE_STORAGE_MINIO_BUCKET_NAME:} - endpoint: ${STATE_STORAGE_MINIO_ENDPOINT:} - secret-access-key: ${STATE_STORAGE_MINIO_SECRET_ACCESS_KEY:} - s3: - access-key: ${STATE_STORAGE_S3_ACCESS_KEY:} - bucket: ${STATE_STORAGE_S3_BUCKET_NAME:} - region: ${STATE_STORAGE_S3_REGION:} - secret-access-key: ${STATE_STORAGE_S3_SECRET_ACCESS_KEY:} - deployment-mode: ${DEPLOYMENT_MODE:OSS} - flyway: - configs: - initialization-timeout-ms: ${CONFIGS_DATABASE_INITIALIZATION_TIMEOUT_MS:60000} - minimum-migration-version: ${CONFIGS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION} - jobs: - initialization-timeout-ms: ${JOBS_DATABASE_INITIALIZATION_TIMEOUT_MS:60000} - minimum-migration-version: ${JOBS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION} - version: ${AIRBYTE_VERSION} - secret: - persistence: ${SECRET_PERSISTENCE:TESTING_CONFIG_DB_TABLE} - store: - aws: - access-key: ${AWS_ACCESS_KEY:} - secret-key: ${AWS_SECRET_ACCESS_KEY:} - gcp: - credentials: ${SECRET_STORE_GCP_CREDENTIALS:} - project-id: ${SECRET_STORE_GCP_PROJECT_ID:} - vault: - address: ${VAULT_ADDRESS:} - prefix: ${VAULT_PREFIX:} - token: ${VAULT_AUTH_TOKEN:} - role: ${AIRBYTE_ROLE:dev} - tracking-strategy: ${TRACKING_STRATEGY:LOGGING} - worker: - job: - error-reporting: - sentry: - dsn: ${JOB_ERROR_REPORTING_SENTRY_DSN} - strategy: ${JOB_ERROR_REPORTING_STRATEGY:LOGGING} - web-app: - url: ${WEBAPP_URL:} - workspace: - root: ${WORKSPACE_ROOT} - protocol: - min-version: ${AIRBYTE_PROTOCOL_VERSION_MIN:0.0.0} - max-version: ${AIRBYTE_PROTOCOL_VERSION_MAX:0.3.0} - -temporal: - cloud: - client: - cert: ${TEMPORAL_CLOUD_CLIENT_CERT:} - key: ${TEMPORAL_CLOUD_CLIENT_KEY:} - enabled: ${TEMPORAL_CLOUD_ENABLED:false} - host: ${TEMPORAL_CLOUD_HOST:} - namespace: ${TEMPORAL_CLOUD_NAMESPACE:} - host: ${TEMPORAL_HOST:`airbyte-temporal:7233`} - retention: ${TEMPORAL_HISTORY_RETENTION_IN_DAYS:30} - -datasources: - config: - connection-test-query: SELECT 1 - connection-timeout: 30000 - maximum-pool-size: 10 - minimum-idle: 0 - idle-timeout: 600000 - initialization-fail-timeout: -1 # Disable fail fast checking to avoid issues due to other pods not being started in time - url: ${DATABASE_URL} - driverClassName: org.postgresql.Driver - username: ${DATABASE_USER} - password: ${DATABASE_PASSWORD} - -endpoints: - beans: - enabled: true - sensitive: false - env: - enabled: true - sensitive: false - health: - enabled: true - sensitive: false - info: - enabled: true - sensitive: true - loggers: - enabled: true - sensitive: true - refresh: - enabled: false - sensitive: true - routes: - enabled: true - sensitive: false - threaddump: - enabled: true - sensitive: true - -flyway: - enabled: true - datasources: - config: - enabled: false - locations: - - "classpath:io/airbyte/db/instance/configs/migrations" - jobs: - enabled: false - locations: - - "classpath:io/airbyte/db/instance/jobs/migrations" - -jooq: - datasources: - config: - jackson-converter-enabled: true - sql-dialect: POSTGRES - jobs: - jackson-converter-enabled: true - sql-dialect: POSTGRES - -logger: - levels: - # Uncomment to help resolve issues with conditional beans - # io.micronaut.context.condition: DEBUG - # Uncomment to help resolve issues with security beans - # io.micronaut.security: DEBUG diff --git a/airbyte-server/src/main/resources/micronaut-banner.txt b/airbyte-server/src/main/resources/micronaut-banner.txt deleted file mode 100644 index 83ea519237a67..0000000000000 --- a/airbyte-server/src/main/resources/micronaut-banner.txt +++ /dev/null @@ -1,11 +0,0 @@ - - ___ _ __ __ - / | (_)____/ /_ __ __/ /____ - / /| | / / ___/ __ \/ / / / __/ _ \ - / ___ |/ / / / /_/ / /_/ / /_/ __/ -/_/ |_/_/_/ /_.___/\__, /\__/\___/ - /____/ - : airbyte-server : --------------------------------------------------- - Will soon be available at http://localhost:8000/ --------------------------------------------------- diff --git a/airbyte-server/src/test/java/io/airbyte/server/apis/HealthCheckApiTest.java b/airbyte-server/src/test/java/io/airbyte/server/apis/HealthCheckApiTest.java deleted file mode 100644 index 34db9e8540fa8..0000000000000 --- a/airbyte-server/src/test/java/io/airbyte/server/apis/HealthCheckApiTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.server.apis; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import io.airbyte.api.model.generated.HealthCheckRead; -import io.airbyte.commons.server.handlers.HealthCheckHandler; -import org.junit.jupiter.api.Test; - -class HealthCheckApiTest { - - @Test - void testImportDefinitions() { - final HealthCheckHandler healthCheckHandler = mock(HealthCheckHandler.class); - when(healthCheckHandler.health()) - .thenReturn(new HealthCheckRead().available( - false)); - - final HealthApiController configurationApi = new HealthApiController(healthCheckHandler); - - assertFalse(configurationApi.getHealthCheck().getAvailable()); - } - -} diff --git a/airbyte-temporal/.gitignore b/airbyte-temporal/.gitignore deleted file mode 100644 index 1fbd8688c4131..0000000000000 --- a/airbyte-temporal/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -scripts/*.tar.gz -scripts/temporal-* diff --git a/airbyte-temporal/Dockerfile b/airbyte-temporal/Dockerfile deleted file mode 100644 index 3ed5b4896570d..0000000000000 --- a/airbyte-temporal/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -# A test describe in the README is available to test a version update -FROM airbyte/temporal-auto-setup:1.13.0 - -ENV TEMPORAL_HOME /etc/temporal - -COPY bin/scripts/update-and-start-temporal.sh update-and-start-temporal.sh - -ENTRYPOINT ["./update-and-start-temporal.sh"] diff --git a/airbyte-temporal/README.md b/airbyte-temporal/README.md deleted file mode 100644 index d085652ea7330..0000000000000 --- a/airbyte-temporal/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# airbyte-temporal - -This module implements a custom version of what the Temporal autosetup image is doing. Because Temporal does not recommend the autosetup be used in production, we had to add some modifications. It ensures that the temporalDB schema will get upgraded if the temporal version is updated. - -## Testing a temporal migration - -`tools/bin/test_temporal_migration.sh` is available to test that a bump of the temporal version won't break the docker compose build. Here is what -the script does: -- checkout master -- build the docker image -- run docker compose up in the background -- Sleep for 75 secondes -- shutdown docker compose -- checkout the commit being tested -- build the docker image -- run docker compose up. - -At the end of the script you should be able to access a local airbyte in `localhost:8000`. - -## Apple Silicon (M1) Support - -Airbyte publishes an image called [airbyte/temporal-auto-setup](https://hub.docker.com/r/airbyte/temporal-auto-setup/tags) which is built for both -Intel-based and ARM-based systems. - -This is because at the time of this writing, Temporal only offers their [temporalio/auto-setup](https://hub.docker.com/r/temporalio/auto-setup) image -for Intel-based (amd64) systems. - -Airbyte re-publishes this image -as [airbyte/temporal-auto-setup:1.13.0-amd64](https://hub.docker.com/layers/airbyte/temporal-auto-setup/1.13.0-amd64/images/sha256-46da05b202e2fa66d9c3f5af5a31b954979d8132c4f67300e884bdad8a45b94d?context=explore) -, and also runs the `build-temporal.sh` script in this repository on an ARM-based system to build and -publish [airbyte/temporal-auto-setup:1.13.0-arm64](https://hub.docker.com/layers/airbyte/temporal-auto-setup/1.13.0-arm64/images/sha256-05027f6a9ba658205c5e961165bb8dad55c95ae0a009eddbf491d12f3d84fe20?context=explore) -. - -Finally, Airbyte creates and publishes a manifest list with both images -as [airbyte/temporal-auto-setup:1.13.0](https://hub.docker.com/layers/airbyte/temporal-auto-setup/1.13.0/images/sha256-46da05b202e2fa66d9c3f5af5a31b954979d8132c4f67300e884bdad8a45b94d?context=explore) -like so: - -```bash -docker manifest create airbyte/temporal-auto-setup:1.13.0 \ ---amend airbyte/temporal-auto-setup:1.13.0-amd64 \ ---amend airbyte/temporal-auto-setup:1.13.0-arm64 -``` - -This process will need to be replicated for any future version upgrades beyond `1.13.0`. See the [original issue](https://github.com/airbytehq/airbyte/issues/8849) for more info. diff --git a/airbyte-temporal/build.gradle b/airbyte-temporal/build.gradle deleted file mode 100644 index e82af665d64d5..0000000000000 --- a/airbyte-temporal/build.gradle +++ /dev/null @@ -1,10 +0,0 @@ -task copyScripts(type: Copy) { - dependsOn copyDocker - - from('scripts') - into 'build/docker/bin/scripts' -} - -tasks.named("buildDockerImage") { - dependsOn copyScripts -} diff --git a/airbyte-temporal/gradle.properties b/airbyte-temporal/gradle.properties deleted file mode 100644 index 4dd7cdd06c6a2..0000000000000 --- a/airbyte-temporal/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=temporal diff --git a/airbyte-temporal/scripts/build-temporal.sh b/airbyte-temporal/scripts/build-temporal.sh deleted file mode 100755 index 3a9d5b7f873da..0000000000000 --- a/airbyte-temporal/scripts/build-temporal.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -TEMPORAL_VERSION=1.13.0 - -curl -OL https://github.com/temporalio/temporal/archive/refs/tags/v"$TEMPORAL_VERSION".tar.gz -tar -xvf v"$TEMPORAL_VERSION".tar.gz -cd temporal-"$TEMPORAL_VERSION" && docker build . -t airbyte/temporal-auto-setup:"$TEMPORAL_VERSION" --build-arg TARGET=auto-setup -rm -rf ../temporal-"$TEMPORAL_VERSION" ../v"$TEMPORAL_VERSION".tar.gz diff --git a/airbyte-temporal/scripts/update-and-start-temporal.sh b/airbyte-temporal/scripts/update-and-start-temporal.sh deleted file mode 100755 index 64da337936c4a..0000000000000 --- a/airbyte-temporal/scripts/update-and-start-temporal.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env bash - -DBNAME="${DBNAME:-temporal}" -VISIBILITY_DBNAME="${VISIBILITY_DBNAME:-temporal_visibility}" -DB_PORT="${DB_PORT:-3306}" - -POSTGRES_SEEDS="${POSTGRES_SEEDS:-}" -POSTGRES_USER="${POSTGRES_USER:-}" -POSTGRES_PWD="${POSTGRES_PWD:-}" - -SCHEMA_DIR=${TEMPORAL_HOME}/schema/postgresql/v96/temporal/versioned -VISIBILITY_SCHEMA_DIR=${TEMPORAL_HOME}/schema/postgresql/v96/visibility/versioned - -SKIP_DEFAULT_NAMESPACE_CREATION="${SKIP_DEFAULT_NAMESPACE_CREATION:-false}" -DEFAULT_NAMESPACE="${DEFAULT_NAMESPACE:-default}" -DEFAULT_NAMESPACE_RETENTION=${DEFAULT_NAMESPACE_RETENTION:-1} - -# See https://github.com/temporalio/temporal/blob/release/v1.13.x/docker/entrypoint.sh -init_entry_point() { - echo "Start init" - export BIND_ON_IP="${BIND_ON_IP:-$(hostname -i)}" - - if [[ "${BIND_ON_IP}" =~ ":" ]]; then - # ipv6 - export TEMPORAL_CLI_ADDRESS="[${BIND_ON_IP}]:7233" - else - # ipv4 - export TEMPORAL_CLI_ADDRESS="${BIND_ON_IP}:7233" - fi - - dockerize -template ./config/config_template.yaml:./config/docker.yaml - echo "Done init" -} - -wait_for_postgres() { - until nc -z "${POSTGRES_SEEDS%%,*}" "${DB_PORT}"; do - echo 'Waiting for PostgreSQL to startup.' - sleep 1 - done - - echo 'PostgreSQL started.' -} - -update_postgres_schema() { - { export SQL_PASSWORD=${POSTGRES_PWD}; } 2> /dev/null - - CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER" - if [ ! -e $CONTAINER_ALREADY_STARTED ]; then - touch $CONTAINER_ALREADY_STARTED - temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" create --db "${DBNAME}" - temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${DBNAME}" setup-schema -v 0.0 - - - temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" create --db "${VISIBILITY_DBNAME}" - temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${VISIBILITY_DBNAME}" setup-schema -v 0.0 - fi - echo "Starting to update the temporal DB" - temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${DBNAME}" update-schema -d "${SCHEMA_DIR}" - echo "Update the temporal DB is done" - - echo "Starting to update the temporal visibility DB" - temporal-sql-tool --plugin postgres --ep "${POSTGRES_SEEDS}" -u "${POSTGRES_USER}" -p "${DB_PORT}" --db "${VISIBILITY_DBNAME}" update-schema -d "${VISIBILITY_SCHEMA_DIR}" - echo "Update the temporal visibility DB is done" - -} - -setup_server(){ - echo "Temporal CLI address: ${TEMPORAL_CLI_ADDRESS}." - - until tctl cluster health | grep SERVING; do - echo "Waiting for Temporal server to start..." - sleep 1 - done - echo "Temporal server started." - - if [ "${SKIP_DEFAULT_NAMESPACE_CREATION}" != true ]; then - register_default_namespace - fi - - if [ "${SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES}" != true ]; then - add_custom_search_attributes - fi -} -register_default_namespace() { - echo "Registering default namespace: ${DEFAULT_NAMESPACE}." - if ! tctl --ns "${DEFAULT_NAMESPACE}" namespace describe; then - echo "Default namespace ${DEFAULT_NAMESPACE} not found. Creating..." - tctl --ns "${DEFAULT_NAMESPACE}" namespace register --rd "${DEFAULT_NAMESPACE_RETENTION}" --desc "Default namespace for Temporal Server." - echo "Default namespace ${DEFAULT_NAMESPACE} registration complete." - else - echo "Default namespace ${DEFAULT_NAMESPACE} already registered." - fi -} - -add_custom_search_attributes() { - echo "Adding Custom*Field search attributes." - # TODO: Remove CustomStringField -# @@@SNIPSTART add-custom-search-attributes-for-testing-command - tctl --auto_confirm admin cluster add-search-attributes \ - --name CustomKeywordField --type Keyword \ - --name CustomStringField --type Text \ - --name CustomTextField --type Text \ - --name CustomIntField --type Int \ - --name CustomDatetimeField --type Datetime \ - --name CustomDoubleField --type Double \ - --name CustomBoolField --type Bool -# @@@SNIPEND -} - -setup_server(){ - echo "Temporal CLI address: ${TEMPORAL_CLI_ADDRESS}." - - until tctl cluster health | grep SERVING; do - echo "Waiting for Temporal server to start..." - sleep 1 - done - echo "Temporal server started." - - if [ "${SKIP_DEFAULT_NAMESPACE_CREATION}" != true ]; then - register_default_namespace - fi - - if [ "${SKIP_ADD_CUSTOM_SEARCH_ATTRIBUTES}" != true ]; then - add_custom_search_attributes - fi -} - -init_entry_point -wait_for_postgres -update_postgres_schema - -echo "starting temporal server" -setup_server & -./start-temporal.sh diff --git a/airbyte-tests/build.gradle b/airbyte-tests/build.gradle deleted file mode 100644 index 23084735b0987..0000000000000 --- a/airbyte-tests/build.gradle +++ /dev/null @@ -1,111 +0,0 @@ -plugins { - id 'java' -} - -// The java plugin automatically compiles/runs tests in the test source set (./src/test directory). Since we want acceptance tests to run -// only when explicitly requested, we put them in a separate source set, specify the sourceset's dependencies via configuration extensions below, -// and create a custom test task that can be invoked to run acceptance tests. -sourceSets { - acceptanceTests { - java { - srcDir("src/acceptanceTests/java") - } - resources { - srcDir("src/acceptanceTests/resources") - } - } - automaticMigrationAcceptanceTest { - java { - srcDir("src/automaticMigrationAcceptanceTest/java") - } - resources { - srcDir("src/automaticMigrationAcceptanceTest/resources") - } - } -} - -// Gradle links configurations with the name xImplementation or xRuntimeOnly etc.. to the source set named x. Therefore, any deps specified -// using the extensions below apply only to this sourceset and not any other code in the project. -configurations { - acceptanceTestsImplementation.extendsFrom testImplementation - acceptanceTestsRuntimeOnly.extendsFrom testRuntimeOnly - - automaticMigrationAcceptanceTestImplementation.extendsFrom testImplementation - automaticMigrationAcceptanceTestRuntimeOnly.extendsFrom testRuntimeOnly -} - -dependencies { - implementation project(':airbyte-api') - implementation project(':airbyte-container-orchestrator') - - implementation 'io.fabric8:kubernetes-client:5.12.2' - implementation libs.platform.testcontainers - - acceptanceTestsImplementation project(':airbyte-api') - acceptanceTestsImplementation project(':airbyte-commons') - acceptanceTestsImplementation project(':airbyte-commons-temporal') - acceptanceTestsImplementation project(':airbyte-config:config-models') - acceptanceTestsImplementation project(':airbyte-config:config-persistence') - acceptanceTestsImplementation project(':airbyte-db:db-lib') - acceptanceTestsImplementation project(':airbyte-tests') - acceptanceTestsImplementation project(':airbyte-test-utils') - acceptanceTestsImplementation project(':airbyte-commons-worker') - - acceptanceTestsImplementation 'com.fasterxml.jackson.core:jackson-databind' - acceptanceTestsImplementation 'io.github.cdimascio:java-dotenv:3.0.0' - acceptanceTestsImplementation libs.temporal.sdk - acceptanceTestsImplementation 'org.apache.commons:commons-csv:1.4' - acceptanceTestsImplementation libs.platform.testcontainers.postgresql - acceptanceTestsImplementation libs.postgresql - acceptanceTestsImplementation 'org.bouncycastle:bcprov-jdk15on:1.66' - acceptanceTestsImplementation 'org.bouncycastle:bcpkix-jdk15on:1.66' - - automaticMigrationAcceptanceTestImplementation project(':airbyte-api') - automaticMigrationAcceptanceTestImplementation project(':airbyte-commons') - automaticMigrationAcceptanceTestImplementation project(':airbyte-tests') - automaticMigrationAcceptanceTestImplementation project(':airbyte-test-utils') - - - automaticMigrationAcceptanceTestImplementation libs.platform.testcontainers -} - -// test should run using the current version of the docker compose configuration. -task copyComposeFileForAcceptanceTests(type: Copy) { - from "${rootDir}/docker-compose.yaml" - into "${sourceSets.acceptanceTests.output.resourcesDir}" -} -task copyComposeFileForMigrationAcceptanceTests(type: Copy) { - from "${rootDir}/docker-compose.yaml" - into "${sourceSets.automaticMigrationAcceptanceTest.output.resourcesDir}" -} - -assemble.dependsOn(project.tasks.copyComposeFileForAcceptanceTests) -assemble.dependsOn(project.tasks.copyComposeFileForMigrationAcceptanceTests) - -task acceptanceTests(type: Test) { - testClassesDirs += sourceSets.acceptanceTests.output.classesDirs - classpath += sourceSets.acceptanceTests.runtimeClasspath - useJUnitPlatform() - failFast = true - testLogging() { - events "passed", "failed" - exceptionFormat "full" - } - mustRunAfter test -} - -task automaticMigrationAcceptanceTest(type: Test) { - testClassesDirs += sourceSets.automaticMigrationAcceptanceTest.output.classesDirs - classpath += sourceSets.automaticMigrationAcceptanceTest.runtimeClasspath - useJUnitPlatform() - failFast = true - testLogging() { - events "passed", "failed" - exceptionFormat "full" - } - mustRunAfter test -} - -tasks.withType(Copy) { - duplicatesStrategy DuplicatesStrategy.INCLUDE -} diff --git a/airbyte-tests/readme.md b/airbyte-tests/readme.md deleted file mode 100644 index eb75f7da3fc1b..0000000000000 --- a/airbyte-tests/readme.md +++ /dev/null @@ -1,5 +0,0 @@ -# airbyte-tests - -This module contains two major test suites: -1. Acceptance Tests - These are feature-level tests that run as part of the build. They spin up Airbyte and test functionality by executing commands against the Airbyte Configuration API. It is possible to run them both on `docker-compose` and `kuberenetes`. We do both in the build. These tests are designed to verify that large features work in broad strokes. More detailed testing should happen in unit tests. -2. Auto Migration Acceptance Tests - These tests verify that it is possible to upgrade from older version of Airbyte (as far back as 0.17.0) all the way up to the current version. diff --git a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/AdvancedAcceptanceTests.java b/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/AdvancedAcceptanceTests.java deleted file mode 100644 index c8324e7b0cf40..0000000000000 --- a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/AdvancedAcceptanceTests.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.acceptance; - -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.COLUMN_ID; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitForConnectionState; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitForSuccessfulJob; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitWhileJobHasStatus; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import io.airbyte.api.client.AirbyteApiClient; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.model.generated.AirbyteCatalog; -import io.airbyte.api.client.model.generated.AirbyteStream; -import io.airbyte.api.client.model.generated.AttemptInfoRead; -import io.airbyte.api.client.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.client.model.generated.ConnectionScheduleType; -import io.airbyte.api.client.model.generated.ConnectionState; -import io.airbyte.api.client.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.DestinationDefinitionRead; -import io.airbyte.api.client.model.generated.DestinationRead; -import io.airbyte.api.client.model.generated.DestinationSyncMode; -import io.airbyte.api.client.model.generated.JobIdRequestBody; -import io.airbyte.api.client.model.generated.JobInfoRead; -import io.airbyte.api.client.model.generated.JobRead; -import io.airbyte.api.client.model.generated.JobStatus; -import io.airbyte.api.client.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.SourceDefinitionRead; -import io.airbyte.api.client.model.generated.SourceRead; -import io.airbyte.api.client.model.generated.SyncMode; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.lang.MoreBooleans; -import io.airbyte.test.utils.AirbyteAcceptanceTestHarness; -import java.io.IOException; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.junitpioneer.jupiter.RetryingTest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The class test for advanced platform functionality that can be affected by the networking - * difference between the Kube and Docker deployments i.e. distributed vs local processes. All tests - * in this class should pass when ran on either type of deployment. - *

- * Tests use the {@link RetryingTest} annotation instead of the more common {@link Test} to allow - * multiple tries for a test to pass. This is because these tests sometimes fail transiently, and we - * haven't been able to fix that yet. - *

- * However, in general we should prefer using {@code @Test} instead and only resort to using - * {@code @RetryingTest} for tests that we can't get to pass reliably. New tests should thus default - * to using {@code @Test} if possible. - *

- * We order tests such that earlier tests test more basic behavior that is relied upon in later - * tests. e.g. We test that we can create a destination before we test whether we can sync data to - * it. - */ -@SuppressWarnings({"rawtypes", "ConstantConditions"}) -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -class AdvancedAcceptanceTests { - - private static final Logger LOGGER = LoggerFactory.getLogger(AdvancedAcceptanceTests.class); - private static final String TYPE = "type"; - private static final String COLUMN1 = "column1"; - - private static AirbyteAcceptanceTestHarness testHarness; - private static AirbyteApiClient apiClient; - private static UUID workspaceId; - - @SuppressWarnings("UnstableApiUsage") - @BeforeAll - static void init() throws URISyntaxException, IOException, InterruptedException, ApiException { - apiClient = new AirbyteApiClient( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - // work in whatever default workspace is present. - workspaceId = apiClient.getWorkspaceApi().listWorkspaces().getWorkspaces().get(0).getWorkspaceId(); - LOGGER.info("workspaceId = " + workspaceId); - - // log which connectors are being used. - final SourceDefinitionRead sourceDef = apiClient.getSourceDefinitionApi() - .getSourceDefinition(new SourceDefinitionIdRequestBody() - .sourceDefinitionId(UUID.fromString("decd338e-5647-4c0b-adf4-da0e75f5a750"))); - final DestinationDefinitionRead destinationDef = apiClient.getDestinationDefinitionApi() - .getDestinationDefinition(new DestinationDefinitionIdRequestBody() - .destinationDefinitionId(UUID.fromString("25c5221d-dce2-4163-ade9-739ef790f503"))); - LOGGER.info("pg source definition: {}", sourceDef.getDockerImageTag()); - LOGGER.info("pg destination definition: {}", destinationDef.getDockerImageTag()); - - testHarness = new AirbyteAcceptanceTestHarness(apiClient, workspaceId); - } - - @AfterAll - static void end() { - testHarness.stopDbAndContainers(); - } - - @BeforeEach - void setup() throws URISyntaxException, IOException, SQLException { - testHarness.setup(); - } - - @AfterEach - void tearDown() { - testHarness.cleanup(); - } - - @RetryingTest(3) - @Order(1) - void testManualSync() throws Exception { - final String connectionName = "test-connection"; - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(connectionName, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead.getJob()); - testHarness.assertSourceAndDestinationDbInSync(false); - } - - @RetryingTest(3) - @Order(2) - void testCheckpointing() throws Exception { - final SourceDefinitionRead sourceDefinition = testHarness.createE2eSourceDefinition(workspaceId); - final DestinationDefinitionRead destinationDefinition = testHarness.createE2eDestinationDefinition(workspaceId); - - final SourceRead source = testHarness.createSource( - "E2E Test Source -" + UUID.randomUUID(), - workspaceId, - sourceDefinition.getSourceDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, "EXCEPTION_AFTER_N") - .put("throw_after_n_records", 100) - .build())); - - final DestinationRead destination = testHarness.createDestination( - "E2E Test Destination -" + UUID.randomUUID(), - workspaceId, - destinationDefinition.getDestinationDefinitionId(), - Jsons.jsonNode(ImmutableMap.of(TYPE, "SILENT"))); - - final String connectionName = "test-connection"; - final UUID sourceId = source.getSourceId(); - final UUID destinationId = destination.getDestinationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final AirbyteStream stream = catalog.getStreams().get(0).getStream(); - - assertEquals( - Lists.newArrayList(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL), - stream.getSupportedSyncModes()); - assertTrue(MoreBooleans.isTruthy(stream.getSourceDefinedCursor())); - - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(connectionName, sourceId, destinationId, Collections.emptyList(), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // wait to get out of pending. - final JobRead runningJob = waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead1.getJob(), Sets.newHashSet(JobStatus.PENDING)); - // wait to get out of running. - waitWhileJobHasStatus(apiClient.getJobsApi(), runningJob, Sets.newHashSet(JobStatus.RUNNING)); - // now cancel it so that we freeze state! - try { - apiClient.getJobsApi().cancelJob(new JobIdRequestBody().id(connectionSyncRead1.getJob().getId())); - } catch (final Exception e) { - LOGGER.error("error:", e); - } - - final ConnectionState connectionState = waitForConnectionState(apiClient, connectionId); - - // the source is set to emit a state message every 5th message. because of the multi threaded - // nature, we can't guarantee exactly what checkpoint will be registered. what we can do is send - // enough messages to make sure that we checkpoint at least once. - assertNotNull(connectionState.getState()); - assertTrue(connectionState.getState().get(COLUMN1).isInt()); - LOGGER.info("state value: {}", connectionState.getState().get(COLUMN1).asInt()); - assertTrue(connectionState.getState().get(COLUMN1).asInt() > 0); - assertEquals(0, connectionState.getState().get(COLUMN1).asInt() % 5); - } - - // verify that when the worker uses backpressure from pipes that no records are lost. - @RetryingTest(3) - @Order(4) - void testBackpressure() throws Exception { - final SourceDefinitionRead sourceDefinition = testHarness.createE2eSourceDefinition(workspaceId); - final DestinationDefinitionRead destinationDefinition = testHarness.createE2eDestinationDefinition(workspaceId); - - final SourceRead source = testHarness.createSource( - "E2E Test Source -" + UUID.randomUUID(), - workspaceId, - sourceDefinition.getSourceDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, "INFINITE_FEED") - .put("max_records", 5000) - .build())); - - final DestinationRead destination = testHarness.createDestination( - "E2E Test Destination -" + UUID.randomUUID(), - workspaceId, - destinationDefinition.getDestinationDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, "THROTTLED") - .put("millis_per_record", 1) - .build())); - - final String connectionName = "test-connection"; - final UUID sourceId = source.getSourceId(); - final UUID destinationId = destination.getDestinationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - final UUID connectionId = - testHarness.createConnection(connectionName, sourceId, destinationId, Collections.emptyList(), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // wait to get out of pending. - final JobRead runningJob = waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead1.getJob(), Sets.newHashSet(JobStatus.PENDING)); - // wait to get out of running. - waitWhileJobHasStatus(apiClient.getJobsApi(), runningJob, Sets.newHashSet(JobStatus.RUNNING)); - - final JobInfoRead jobInfo = apiClient.getJobsApi().getJobInfo(new JobIdRequestBody().id(runningJob.getId())); - final AttemptInfoRead attemptInfoRead = jobInfo.getAttempts().get(jobInfo.getAttempts().size() - 1); - assertNotNull(attemptInfoRead); - - int expectedMessageNumber = 0; - final int max = 10_000; - for (final String logLine : attemptInfoRead.getLogs().getLogLines()) { - if (expectedMessageNumber > max) { - break; - } - - if (logLine.contains("received record: ") && logLine.contains("\"type\": \"RECORD\"")) { - assertTrue( - logLine.contains(String.format("\"column1\": \"%s\"", expectedMessageNumber)), - String.format("Expected %s but got: %s", expectedMessageNumber, logLine)); - expectedMessageNumber++; - } - } - } - -} diff --git a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/BasicAcceptanceTests.java b/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/BasicAcceptanceTests.java deleted file mode 100644 index 3e7cf2888f757..0000000000000 --- a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/BasicAcceptanceTests.java +++ /dev/null @@ -1,1594 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.acceptance; - -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.AWESOME_PEOPLE_TABLE_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.COLUMN_ID; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.COLUMN_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.COOL_EMPLOYEES_TABLE_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.PUBLIC_SCHEMA_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.STAGING_SCHEMA_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.STREAM_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitForSuccessfulJob; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitWhileJobHasStatus; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitWhileJobIsRunning; -import static java.lang.Thread.sleep; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import io.airbyte.api.client.AirbyteApiClient; -import io.airbyte.api.client.generated.WebBackendApi; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.model.generated.AirbyteCatalog; -import io.airbyte.api.client.model.generated.AirbyteStream; -import io.airbyte.api.client.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.client.model.generated.AirbyteStreamConfiguration; -import io.airbyte.api.client.model.generated.AttemptInfoRead; -import io.airbyte.api.client.model.generated.AttemptStatus; -import io.airbyte.api.client.model.generated.CheckConnectionRead; -import io.airbyte.api.client.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.client.model.generated.ConnectionRead; -import io.airbyte.api.client.model.generated.ConnectionScheduleData; -import io.airbyte.api.client.model.generated.ConnectionScheduleDataBasicSchedule; -import io.airbyte.api.client.model.generated.ConnectionScheduleDataBasicSchedule.TimeUnitEnum; -import io.airbyte.api.client.model.generated.ConnectionScheduleDataCron; -import io.airbyte.api.client.model.generated.ConnectionScheduleType; -import io.airbyte.api.client.model.generated.ConnectionState; -import io.airbyte.api.client.model.generated.ConnectionStatus; -import io.airbyte.api.client.model.generated.DataType; -import io.airbyte.api.client.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.DestinationDefinitionIdWithWorkspaceId; -import io.airbyte.api.client.model.generated.DestinationDefinitionRead; -import io.airbyte.api.client.model.generated.DestinationDefinitionSpecificationRead; -import io.airbyte.api.client.model.generated.DestinationIdRequestBody; -import io.airbyte.api.client.model.generated.DestinationRead; -import io.airbyte.api.client.model.generated.DestinationSyncMode; -import io.airbyte.api.client.model.generated.JobConfigType; -import io.airbyte.api.client.model.generated.JobIdRequestBody; -import io.airbyte.api.client.model.generated.JobInfoRead; -import io.airbyte.api.client.model.generated.JobListRequestBody; -import io.airbyte.api.client.model.generated.JobRead; -import io.airbyte.api.client.model.generated.JobStatus; -import io.airbyte.api.client.model.generated.JobWithAttemptsRead; -import io.airbyte.api.client.model.generated.OperationCreate; -import io.airbyte.api.client.model.generated.OperationRead; -import io.airbyte.api.client.model.generated.OperatorConfiguration; -import io.airbyte.api.client.model.generated.OperatorType; -import io.airbyte.api.client.model.generated.OperatorWebhook; -import io.airbyte.api.client.model.generated.OperatorWebhook.WebhookTypeEnum; -import io.airbyte.api.client.model.generated.OperatorWebhookDbtCloud; -import io.airbyte.api.client.model.generated.SelectedFieldInfo; -import io.airbyte.api.client.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.SourceDefinitionIdWithWorkspaceId; -import io.airbyte.api.client.model.generated.SourceDefinitionRead; -import io.airbyte.api.client.model.generated.SourceDefinitionSpecificationRead; -import io.airbyte.api.client.model.generated.SourceIdRequestBody; -import io.airbyte.api.client.model.generated.SourceRead; -import io.airbyte.api.client.model.generated.StreamDescriptor; -import io.airbyte.api.client.model.generated.StreamState; -import io.airbyte.api.client.model.generated.SyncMode; -import io.airbyte.api.client.model.generated.WebBackendConnectionUpdate; -import io.airbyte.api.client.model.generated.WebhookConfigWrite; -import io.airbyte.api.client.model.generated.WorkspaceRead; -import io.airbyte.api.client.model.generated.WorkspaceUpdate; -import io.airbyte.commons.json.Jsons; -import io.airbyte.commons.temporal.scheduling.state.WorkflowState; -import io.airbyte.db.Database; -import io.airbyte.db.jdbc.JdbcUtils; -import io.airbyte.test.utils.AirbyteAcceptanceTestHarness; -import io.airbyte.test.utils.PostgreSQLContainerHelper; -import io.airbyte.test.utils.SchemaTableNamePair; -import java.io.IOException; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.time.Duration; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; -import org.jooq.DSLContext; -import org.jooq.impl.DSL; -import org.jooq.impl.SQLDataType; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.utility.MountableFile; - -/** - * This class tests for api functionality and basic sync functionality. - *

- * Due to the number of tests here, this set runs only on the docker deployment for speed. The tests - * here are disabled for Kubernetes as operations take much longer due to Kubernetes pod spin up - * times and there is little value in re-running these tests since this part of the system does not - * vary between deployments. - *

- * We order tests such that earlier tests test more basic behavior relied upon in later tests. e.g. - * We test that we can create a destination before we test whether we can sync data to it. - */ -@DisabledIfEnvironmentVariable(named = "KUBE", - matches = "true") -@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") -class BasicAcceptanceTests { - - private static final Logger LOGGER = LoggerFactory.getLogger(BasicAcceptanceTests.class); - - private static final Boolean WITH_SCD_TABLE = true; - - private static final Boolean WITHOUT_SCD_TABLE = false; - - private static AirbyteAcceptanceTestHarness testHarness; - private static AirbyteApiClient apiClient; - private static WebBackendApi webBackendApi; - private static UUID workspaceId; - private static PostgreSQLContainer sourcePsql; - - private static final String TYPE = "type"; - private static final String REF = "$ref"; - private static final String INTEGER_REFERENCE = "WellKnownTypes.json#/definitions/Integer"; - private static final String STRING_REFERENCE = "WellKnownTypes.json#/definitions/String"; - private static final String PUBLIC = "public"; - private static final String E2E_TEST_SOURCE = "E2E Test Source -"; - private static final String INFINITE_FEED = "INFINITE_FEED"; - private static final String MESSAGE_INTERVAL = "message_interval"; - private static final String MAX_RECORDS = "max_records"; - private static final String TEST_CONNECTION = "test-connection"; - private static final String STATE_AFTER_SYNC_ONE = "state after sync 1: {}"; - private static final String STATE_AFTER_SYNC_TWO = "state after sync 2: {}"; - private static final String GERALT = "geralt"; - private static final String NAME = "name"; - private static final String VALUE = "value"; - private static final String LOCATION = "location"; - private static final String FIELD = "field"; - private static final String ID_AND_NAME = "id_and_name"; - - private static final int MAX_SCHEDULED_JOB_RETRIES = 10; - - private static final ConnectionScheduleData BASIC_SCHEDULE_DATA = new ConnectionScheduleData().basicSchedule( - new ConnectionScheduleDataBasicSchedule().units(1L).timeUnit(TimeUnitEnum.HOURS)); - - @BeforeAll - static void init() throws URISyntaxException, IOException, InterruptedException, ApiException { - apiClient = new AirbyteApiClient( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - webBackendApi = new WebBackendApi( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - // work in whatever default workspace is present. - workspaceId = apiClient.getWorkspaceApi().listWorkspaces().getWorkspaces().get(0).getWorkspaceId(); - LOGGER.info("workspaceId = " + workspaceId); - - // log which connectors are being used. - final SourceDefinitionRead sourceDef = apiClient.getSourceDefinitionApi() - .getSourceDefinition(new SourceDefinitionIdRequestBody() - .sourceDefinitionId(UUID.fromString("decd338e-5647-4c0b-adf4-da0e75f5a750"))); - final DestinationDefinitionRead destinationDef = apiClient.getDestinationDefinitionApi() - .getDestinationDefinition(new DestinationDefinitionIdRequestBody() - .destinationDefinitionId(UUID.fromString("25c5221d-dce2-4163-ade9-739ef790f503"))); - LOGGER.info("pg source definition: {}", sourceDef.getDockerImageTag()); - LOGGER.info("pg destination definition: {}", destinationDef.getDockerImageTag()); - - testHarness = new AirbyteAcceptanceTestHarness(apiClient, workspaceId); - sourcePsql = testHarness.getSourcePsql(); - } - - @AfterAll - static void end() { - testHarness.stopDbAndContainers(); - } - - @BeforeEach - void setup() throws SQLException, URISyntaxException, IOException { - testHarness.setup(); - } - - @AfterEach - void tearDown() { - testHarness.cleanup(); - } - - @Test - @Order(-2) - void testGetDestinationSpec() throws ApiException { - final UUID destinationDefinitionId = testHarness.getPostgresDestinationDefinitionId(); - final DestinationDefinitionSpecificationRead spec = apiClient.getDestinationDefinitionSpecificationApi() - .getDestinationDefinitionSpecification( - new DestinationDefinitionIdWithWorkspaceId().destinationDefinitionId(destinationDefinitionId).workspaceId(UUID.randomUUID())); - assertEquals(destinationDefinitionId, spec.getDestinationDefinitionId()); - assertNotNull(spec.getConnectionSpecification()); - } - - @Test - @Order(-1) - void testFailedGet404() { - final var e = assertThrows(ApiException.class, () -> apiClient.getDestinationDefinitionSpecificationApi() - .getDestinationDefinitionSpecification( - new DestinationDefinitionIdWithWorkspaceId().destinationDefinitionId(UUID.randomUUID()).workspaceId(UUID.randomUUID()))); - assertEquals(404, e.getCode()); - } - - @Test - @Order(0) - void testGetSourceSpec() throws ApiException { - final UUID sourceDefId = testHarness.getPostgresSourceDefinitionId(); - final SourceDefinitionSpecificationRead spec = apiClient.getSourceDefinitionSpecificationApi() - .getSourceDefinitionSpecification(new SourceDefinitionIdWithWorkspaceId().sourceDefinitionId(sourceDefId).workspaceId(UUID.randomUUID())); - assertEquals(sourceDefId, spec.getSourceDefinitionId()); - assertNotNull(spec.getConnectionSpecification()); - } - - @Test - @Order(1) - void testCreateDestination() throws ApiException { - final UUID destinationDefId = testHarness.getPostgresDestinationDefinitionId(); - final JsonNode destinationConfig = testHarness.getDestinationDbConfig(); - final String name = "AccTestDestinationDb-" + UUID.randomUUID(); - - final DestinationRead createdDestination = testHarness.createDestination( - name, - workspaceId, - destinationDefId, - destinationConfig); - - assertEquals(name, createdDestination.getName()); - assertEquals(destinationDefId, createdDestination.getDestinationDefinitionId()); - assertEquals(workspaceId, createdDestination.getWorkspaceId()); - assertEquals(testHarness.getDestinationDbConfigWithHiddenPassword(), createdDestination.getConnectionConfiguration()); - } - - @Test - @Order(2) - void testDestinationCheckConnection() throws ApiException { - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - - final CheckConnectionRead.StatusEnum checkOperationStatus = apiClient.getDestinationApi() - .checkConnectionToDestination(new DestinationIdRequestBody().destinationId(destinationId)) - .getStatus(); - - assertEquals(CheckConnectionRead.StatusEnum.SUCCEEDED, checkOperationStatus); - } - - @Test - @Order(3) - void wtestCreateSource() throws ApiException { - final String dbName = "acc-test-db"; - final UUID postgresSourceDefinitionId = testHarness.getPostgresSourceDefinitionId(); - final JsonNode sourceDbConfig = testHarness.getSourceDbConfig(); - - final SourceRead response = testHarness.createSource( - dbName, - workspaceId, - postgresSourceDefinitionId, - sourceDbConfig); - - final JsonNode expectedConfig = Jsons.jsonNode(sourceDbConfig); - // expect replacement of secret with magic string. - ((ObjectNode) expectedConfig).put(JdbcUtils.PASSWORD_KEY, "**********"); - assertEquals(dbName, response.getName()); - assertEquals(workspaceId, response.getWorkspaceId()); - assertEquals(postgresSourceDefinitionId, response.getSourceDefinitionId()); - assertEquals(expectedConfig, response.getConnectionConfiguration()); - } - - @Test - @Order(4) - void testSourceCheckConnection() throws ApiException { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - - final CheckConnectionRead checkConnectionRead = apiClient.getSourceApi().checkConnectionToSource(new SourceIdRequestBody().sourceId(sourceId)); - - assertEquals( - CheckConnectionRead.StatusEnum.SUCCEEDED, - checkConnectionRead.getStatus(), - checkConnectionRead.getMessage()); - } - - @Test - @Order(5) - void testDiscoverSourceSchema() throws ApiException { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - - final AirbyteCatalog actual = testHarness.discoverSourceSchema(sourceId); - - final Map> fields = ImmutableMap.of( - COLUMN_ID, ImmutableMap.of(TYPE, DataType.NUMBER.getValue(), "airbyte_type", "integer"), - COLUMN_NAME, ImmutableMap.of(TYPE, DataType.STRING.getValue())); - final JsonNode jsonSchema = Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, "object") - .put("properties", fields) - .build()); - final AirbyteStream stream = new AirbyteStream() - .name(STREAM_NAME) - .namespace(PUBLIC) - .jsonSchema(jsonSchema) - .sourceDefinedCursor(null) - .defaultCursorField(Collections.emptyList()) - .sourceDefinedPrimaryKey(Collections.emptyList()) - .supportedSyncModes(List.of(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL)); - final AirbyteStreamConfiguration streamConfig = new AirbyteStreamConfiguration() - .syncMode(SyncMode.FULL_REFRESH) - .cursorField(Collections.emptyList()) - .destinationSyncMode(DestinationSyncMode.APPEND) - .primaryKey(Collections.emptyList()) - .aliasName(STREAM_NAME.replace(".", "_")) - .selected(true) - .suggested(true); - final AirbyteCatalog expected = new AirbyteCatalog() - .streams(Lists.newArrayList(new AirbyteStreamAndConfiguration() - .stream(stream) - .config(streamConfig))); - - assertEquals(expected, actual); - } - - @Test - @Order(6) - void testCreateConnection() throws ApiException { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final String name = "test-connection-" + UUID.randomUUID(); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode).setFieldSelectionEnabled(false)); - final ConnectionRead createdConnection = - testHarness.createConnection(name, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.BASIC, BASIC_SCHEDULE_DATA); - createdConnection.getSyncCatalog().getStreams().forEach(s -> s.getConfig().setSuggested(true)); - - assertEquals(sourceId, createdConnection.getSourceId()); - assertEquals(destinationId, createdConnection.getDestinationId()); - assertEquals(1, createdConnection.getOperationIds().size()); - assertEquals(operationId, createdConnection.getOperationIds().get(0)); - assertEquals(catalog, createdConnection.getSyncCatalog()); - assertEquals(ConnectionScheduleType.BASIC, createdConnection.getScheduleType()); - assertEquals(BASIC_SCHEDULE_DATA, createdConnection.getScheduleData()); - assertEquals(name, createdConnection.getName()); - } - - @Test - @Order(7) - void testCancelSync() throws Exception { - final SourceDefinitionRead sourceDefinition = testHarness.createE2eSourceDefinition(workspaceId); - - final SourceRead source = testHarness.createSource( - E2E_TEST_SOURCE + UUID.randomUUID(), - workspaceId, - sourceDefinition.getSourceDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, INFINITE_FEED) - .put(MESSAGE_INTERVAL, 1000) - .put(MAX_RECORDS, Duration.ofMinutes(5).toSeconds()) - .build())); - - final UUID sourceId = source.getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // wait to get out of PENDING - final JobRead jobRead = waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead.getJob(), Set.of(JobStatus.PENDING)); - assertEquals(JobStatus.RUNNING, jobRead.getStatus()); - - final var resp = apiClient.getJobsApi().cancelJob(new JobIdRequestBody().id(connectionSyncRead.getJob().getId())); - assertEquals(JobStatus.CANCELLED, resp.getJob().getStatus()); - } - - @Test - @Order(8) - void testScheduledSync() throws Exception { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.BASIC, - BASIC_SCHEDULE_DATA).getConnectionId(); - - waitForSuccessfulJobWithRetries(connectionId, MAX_SCHEDULED_JOB_RETRIES); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - } - - @Test - @Order(9) - void testCronSync() throws Exception { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - // NOTE: this cron should run once every two minutes. - final ConnectionScheduleData connectionScheduleData = new ConnectionScheduleData().cron( - new ConnectionScheduleDataCron().cronExpression("* */2 * * * ?").cronTimeZone("UTC")); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.CRON, - connectionScheduleData).getConnectionId(); - - waitForSuccessfulJobWithRetries(connectionId, MAX_SCHEDULED_JOB_RETRIES); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - apiClient.getConnectionApi().deleteConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // remove connection to avoid exception during tear down - testHarness.removeConnection(connectionId); - } - - @Test - @Order(19) - void testWebhookOperationExecutesSuccessfully() throws Exception { - // create workspace webhook config - final WorkspaceRead workspaceRead = apiClient.getWorkspaceApi().updateWorkspace( - new WorkspaceUpdate().workspaceId(workspaceId).addWebhookConfigsItem( - new WebhookConfigWrite().name("reqres test"))); - // create a webhook operation - final OperationRead operationRead = apiClient.getOperationApi().createOperation(new OperationCreate() - .workspaceId(workspaceId) - .name("reqres test") - .operatorConfiguration(new OperatorConfiguration() - .operatorType(OperatorType.WEBHOOK) - .webhook(new OperatorWebhook() - .webhookConfigId(workspaceRead.getWebhookConfigs().get(0).getId()) - // NOTE: this dbt Cloud config won't actually work, but the sync should still succeed. - .webhookType(WebhookTypeEnum.DBTCLOUD) - .dbtCloud(new OperatorWebhookDbtCloud().accountId(123).jobId(456))))); - // create a connection with the new operation. - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - // NOTE: this is a normalization operation. - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection( - TEST_CONNECTION, sourceId, destinationId, List.of(operationId, operationRead.getOperationId()), catalog, ConnectionScheduleType.MANUAL, - null) - .getConnectionId(); - // run the sync - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJobWithRetries(connectionId, MAX_SCHEDULED_JOB_RETRIES); - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - apiClient.getConnectionApi().deleteConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - // remove connection to avoid exception during tear down - testHarness.removeConnection(connectionId); - // TODO(mfsiega-airbyte): add webhook info to the jobs api to verify the webhook execution status. - } - - @Test - @Order(10) - void testMultipleSchemasAndTablesSync() throws Exception { - // create tables in another schema - PostgreSQLContainerHelper.runSqlScript(MountableFile.forClasspathResource("postgres_second_schema_multiple_tables.sql"), sourcePsql); - - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead.getJob()); - testHarness.assertSourceAndDestinationDbInSync(false); - } - - @Test - @Order(11) - void testMultipleSchemasSameTablesSync() throws Exception { - // create tables in another schema - PostgreSQLContainerHelper.runSqlScript(MountableFile.forClasspathResource("postgres_separate_schema_same_table.sql"), sourcePsql); - - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead.getJob()); - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - } - - @Test - @Order(12) - void testIncrementalDedupeSync() throws Exception { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND_DEDUP; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode) - .primaryKey(List.of(List.of(COLUMN_NAME)))); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - // sync from start - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - - testHarness.assertSourceAndDestinationDbInSync(WITH_SCD_TABLE); - - // add new records and run again. - final Database source = testHarness.getSourceDatabase(); - final List expectedRawRecords = testHarness.retrieveSourceRecords(source, STREAM_NAME); - expectedRawRecords.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, "sherif").build())); - expectedRawRecords.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 7).put(COLUMN_NAME, "chris").build())); - source.query(ctx -> ctx.execute("UPDATE id_and_name SET id=6 WHERE name='sherif'")); - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(7, 'chris')")); - // retrieve latest snapshot of source records after modifications; the deduplicated table in - // destination should mirror this latest state of records - final List expectedNormalizedRecords = testHarness.retrieveSourceRecords(source, STREAM_NAME); - - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - - testHarness.assertRawDestinationContains(expectedRawRecords, new SchemaTableNamePair(PUBLIC, STREAM_NAME)); - testHarness.assertNormalizedDestinationContains(expectedNormalizedRecords); - } - - @Test - @Order(13) - void testIncrementalSync() throws Exception { - LOGGER.info("Starting testIncrementalSync()"); - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final AirbyteStream stream = catalog.getStreams().get(0).getStream(); - - assertEquals(Lists.newArrayList(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL), stream.getSupportedSyncModes()); - // instead of assertFalse to avoid NPE from unboxed. - assertNull(stream.getSourceDefinedCursor()); - assertTrue(stream.getDefaultCursorField().isEmpty()); - assertTrue(stream.getSourceDefinedPrimaryKey().isEmpty()); - - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - LOGGER.info("Beginning testIncrementalSync() sync 1"); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - LOGGER.info(STATE_AFTER_SYNC_ONE, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - - // add new records and run again. - final Database source = testHarness.getSourceDatabase(); - // get contents of source before mutating records. - final List expectedRecords = testHarness.retrieveSourceRecords(source, STREAM_NAME); - expectedRecords.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, GERALT).build())); - // add a new record - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(6, 'geralt')")); - // mutate a record that was already synced with out updating its cursor value. if we are actually - // full refreshing, this record will appear in the output and cause the test to fail. if we are, - // correctly, doing incremental, we will not find this value in the destination. - source.query(ctx -> ctx.execute("UPDATE id_and_name SET name='yennefer' WHERE id=2")); - - LOGGER.info("Starting testIncrementalSync() sync 2"); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - LOGGER.info(STATE_AFTER_SYNC_TWO, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertRawDestinationContains(expectedRecords, new SchemaTableNamePair(PUBLIC, STREAM_NAME)); - - // reset back to no data. - - LOGGER.info("Starting testIncrementalSync() reset"); - final JobInfoRead jobInfoRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitWhileJobHasStatus(apiClient.getJobsApi(), jobInfoRead.getJob(), - Sets.newHashSet(JobStatus.PENDING, JobStatus.RUNNING, JobStatus.INCOMPLETE, JobStatus.FAILED)); - // This is a band-aid to prevent some race conditions where the job status was updated but we may - // still be cleaning up some data in the reset table. This would be an argument for reworking the - // source of truth of the replication workflow state to be in DB rather than in Memory and - // serialized automagically by temporal - waitWhileJobIsRunning(apiClient.getJobsApi(), jobInfoRead.getJob(), Duration.ofMinutes(1)); - - LOGGER.info("state after reset: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertRawDestinationContains(Collections.emptyList(), new SchemaTableNamePair(PUBLIC, - STREAM_NAME)); - - // sync one more time. verify it is the equivalent of a full refresh. - LOGGER.info("Starting testIncrementalSync() sync 3"); - final JobInfoRead connectionSyncRead3 = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead3.getJob()); - LOGGER.info("state after sync 3: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - - } - - @Test - @Order(14) - void testDeleteConnection() throws Exception { - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND_DEDUP; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode) - .primaryKey(List.of(List.of(COLUMN_NAME)))); - - UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead.getJob(), Set.of(JobStatus.RUNNING)); - - // test normal deletion of connection - LOGGER.info("Calling delete connection..."); - apiClient.getConnectionApi().deleteConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // remove connection to avoid exception during tear down - // connectionIds.remove(connectionId); // todo remove - testHarness.removeConnection(connectionId); - - ConnectionStatus connectionStatus = - apiClient.getConnectionApi().getConnection(new ConnectionIdRequestBody().connectionId(connectionId)).getStatus(); - assertEquals(ConnectionStatus.DEPRECATED, connectionStatus); - - // test that repeated deletion call for same connection is successful - LOGGER.info("Calling delete connection a second time to test repeat call behavior..."); - apiClient.getConnectionApi().deleteConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // test deletion of connection when temporal workflow is in a bad state - LOGGER.info("Testing connection deletion when temporal is in a terminal state"); - connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - testHarness.terminateTemporalWorkflow(connectionId); - - // we should still be able to delete the connection when the temporal workflow is in this state - apiClient.getConnectionApi().deleteConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - connectionStatus = apiClient.getConnectionApi().getConnection(new ConnectionIdRequestBody().connectionId(connectionId)).getStatus(); - assertEquals(ConnectionStatus.DEPRECATED, connectionStatus); - } - - @Test - @Order(15) - void testUpdateConnectionWhenWorkflowUnreachable() throws Exception { - // This test only covers the specific behavior of updating a connection that does not have an - // underlying temporal workflow. - // Also, this test doesn't verify correctness of the schedule update applied, as adding the ability - // to query a workflow for its current - // schedule is out of scope for the issue (https://github.com/airbytehq/airbyte/issues/11215). This - // test just ensures that the underlying workflow - // is running after the update method is called. - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(DestinationSyncMode.APPEND_DEDUP) - .primaryKey(List.of(List.of(COLUMN_NAME)))); - - LOGGER.info("Testing connection update when temporal is in a terminal state"); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - testHarness.terminateTemporalWorkflow(connectionId); - - // we should still be able to update the connection when the temporal workflow is in this state - testHarness.updateConnectionSchedule( - connectionId, - ConnectionScheduleType.BASIC, - new ConnectionScheduleData().basicSchedule(new ConnectionScheduleDataBasicSchedule().timeUnit(TimeUnitEnum.HOURS).units(1L))); - - LOGGER.info("Waiting for workflow to be recreated..."); - Thread.sleep(500); - - final WorkflowState workflowState = testHarness.getWorkflowState(connectionId); - assertTrue(workflowState.isRunning()); - } - - @Test - @Order(16) - void testManualSyncRepairsWorkflowWhenWorkflowUnreachable() throws Exception { - // This test only covers the specific behavior of updating a connection that does not have an - // underlying temporal workflow. - final SourceDefinitionRead sourceDefinition = testHarness.createE2eSourceDefinition(workspaceId); - final SourceRead source = testHarness.createSource( - E2E_TEST_SOURCE + UUID.randomUUID(), - workspaceId, - sourceDefinition.getSourceDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, INFINITE_FEED) - .put(MAX_RECORDS, 5000) - .put(MESSAGE_INTERVAL, 100) - .build())); - final UUID sourceId = source.getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(DestinationSyncMode.APPEND_DEDUP) - .primaryKey(List.of(List.of(COLUMN_NAME)))); - - LOGGER.info("Testing manual sync when temporal is in a terminal state"); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - LOGGER.info("Starting first manual sync"); - final JobInfoRead firstJobInfo = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - LOGGER.info("Terminating workflow during first sync"); - testHarness.terminateTemporalWorkflow(connectionId); - - LOGGER.info("Submitted another manual sync"); - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - LOGGER.info("Waiting for workflow to be recreated..."); - Thread.sleep(500); - - final WorkflowState workflowState = testHarness.getWorkflowState(connectionId); - assertTrue(workflowState.isRunning()); - assertTrue(workflowState.isSkipScheduling()); - - // verify that the first manual sync was marked as failed - final JobInfoRead terminatedJobInfo = apiClient.getJobsApi().getJobInfo(new JobIdRequestBody().id(firstJobInfo.getJob().getId())); - assertEquals(JobStatus.FAILED, terminatedJobInfo.getJob().getStatus()); - } - - @Test - @Order(17) - void testResetConnectionRepairsWorkflowWhenWorkflowUnreachable() throws Exception { - // This test only covers the specific behavior of updating a connection that does not have an - // underlying temporal workflow. - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(DestinationSyncMode.APPEND_DEDUP) - .primaryKey(List.of(List.of(COLUMN_NAME)))); - - LOGGER.info("Testing reset connection when temporal is in a terminal state"); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - testHarness.terminateTemporalWorkflow(connectionId); - - final JobInfoRead jobInfoRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - assertEquals(JobConfigType.RESET_CONNECTION, jobInfoRead.getJob().getConfigType()); - } - - @Test - @Order(18) - void testResetCancelsRunningSync() throws Exception { - final SourceDefinitionRead sourceDefinition = testHarness.createE2eSourceDefinition(workspaceId); - - final SourceRead source = testHarness.createSource( - E2E_TEST_SOURCE + UUID.randomUUID(), - workspaceId, - sourceDefinition.getSourceDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, INFINITE_FEED) - .put(MESSAGE_INTERVAL, 1000) - .put(MAX_RECORDS, Duration.ofMinutes(5).toSeconds()) - .build())); - - final UUID sourceId = source.getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // wait to get out of PENDING - final JobRead jobRead = waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead.getJob(), Set.of(JobStatus.PENDING)); - assertEquals(JobStatus.RUNNING, jobRead.getStatus()); - - // send reset request while sync is still running - final JobInfoRead jobInfoRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - assertEquals(JobConfigType.RESET_CONNECTION, jobInfoRead.getJob().getConfigType()); - - // verify that sync job was cancelled - final JobRead connectionSyncReadAfterReset = - apiClient.getJobsApi().getJobInfo(new JobIdRequestBody().id(connectionSyncRead.getJob().getId())).getJob(); - assertEquals(JobStatus.CANCELLED, connectionSyncReadAfterReset.getStatus()); - } - - @Test - void testSyncAfterUpgradeToPerStreamState(final TestInfo testInfo) throws Exception { - LOGGER.info("Starting {}", testInfo.getDisplayName()); - final SourceRead source = testHarness.createPostgresSource(true); - final UUID sourceId = source.getSourceId(); - final UUID sourceDefinitionId = source.getSourceDefinitionId(); - final UUID destinationId = testHarness.createPostgresDestination(true).getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - // Fetch the current/most recent source definition version - final SourceDefinitionRead sourceDefinitionRead = - apiClient.getSourceDefinitionApi().getSourceDefinition(new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceDefinitionId)); - final String currentSourceDefintionVersion = sourceDefinitionRead.getDockerImageTag(); - - // Set the source to a version that does not support per-stream state - LOGGER.info("Setting source connector to pre-per-stream state version {}...", - AirbyteAcceptanceTestHarness.POSTGRES_SOURCE_LEGACY_CONNECTOR_VERSION); - testHarness.updateSourceDefinitionVersion(sourceDefinitionId, AirbyteAcceptanceTestHarness.POSTGRES_SOURCE_LEGACY_CONNECTOR_VERSION); - - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(DestinationSyncMode.APPEND)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - LOGGER.info("Beginning {} sync 1", testInfo.getDisplayName()); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - LOGGER.info(STATE_AFTER_SYNC_ONE, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - - // Set source to a version that supports per-stream state - testHarness.updateSourceDefinitionVersion(sourceDefinitionId, currentSourceDefintionVersion); - LOGGER.info("Upgraded source connector per-stream state supported version {}.", currentSourceDefintionVersion); - - // add new records and run again. - final Database sourceDatabase = testHarness.getSourceDatabase(); - // get contents of source before mutating records. - final List expectedRecords = testHarness.retrieveSourceRecords(sourceDatabase, STREAM_NAME); - expectedRecords.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, GERALT).build())); - // add a new record - sourceDatabase.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(6, 'geralt')")); - // mutate a record that was already synced with out updating its cursor value. if we are actually - // full refreshing, this record will appear in the output and cause the test to fail. if we are, - // correctly, doing incremental, we will not find this value in the destination. - sourceDatabase.query(ctx -> ctx.execute("UPDATE id_and_name SET name='yennefer' WHERE id=2")); - - LOGGER.info("Starting {} sync 2", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - LOGGER.info(STATE_AFTER_SYNC_TWO, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertRawDestinationContains(expectedRecords, new SchemaTableNamePair(PUBLIC, STREAM_NAME)); - - // reset back to no data. - LOGGER.info("Starting {} reset", testInfo.getDisplayName()); - final JobInfoRead jobInfoRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitWhileJobHasStatus(apiClient.getJobsApi(), jobInfoRead.getJob(), - Sets.newHashSet(JobStatus.PENDING, JobStatus.RUNNING, JobStatus.INCOMPLETE, JobStatus.FAILED)); - // This is a band-aid to prevent some race conditions where the job status was updated but we may - // still be cleaning up some data in the reset table. This would be an argument for reworking the - // source of truth of the replication workflow state to be in DB rather than in Memory and - // serialized automagically by temporal - waitWhileJobIsRunning(apiClient.getJobsApi(), jobInfoRead.getJob(), Duration.ofMinutes(1)); - - LOGGER.info("state after reset: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertRawDestinationContains(Collections.emptyList(), new SchemaTableNamePair(PUBLIC, - STREAM_NAME)); - - // sync one more time. verify it is the equivalent of a full refresh. - final String expectedState = - "{\"cursor\":\"6\",\"stream_name\":\"id_and_name\",\"cursor_field\":[\"id\"],\"stream_namespace\":\"public\",\"cursor_record_count\":1}"; - LOGGER.info("Starting {} sync 3", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead3 = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead3.getJob()); - final ConnectionState state = apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId)); - LOGGER.info("state after sync 3: {}", state); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - assertNotNull(state.getStreamState()); - assertEquals(1, state.getStreamState().size()); - final StreamState idAndNameState = state.getStreamState().get(0); - assertEquals(new StreamDescriptor().namespace(PUBLIC).name(STREAM_NAME), idAndNameState.getStreamDescriptor()); - assertEquals(Jsons.deserialize(expectedState), idAndNameState.getStreamState()); - } - - @Test - void testSyncAfterUpgradeToPerStreamStateWithNoNewData(final TestInfo testInfo) throws Exception { - LOGGER.info("Starting {}", testInfo.getDisplayName()); - final SourceRead source = testHarness.createPostgresSource(true); - final UUID sourceId = source.getSourceId(); - final UUID sourceDefinitionId = source.getSourceDefinitionId(); - final UUID destinationId = testHarness.createPostgresDestination(true).getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - // Fetch the current/most recent source definition version - final SourceDefinitionRead sourceDefinitionRead = - apiClient.getSourceDefinitionApi().getSourceDefinition(new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceDefinitionId)); - final String currentSourceDefintionVersion = sourceDefinitionRead.getDockerImageTag(); - - // Set the source to a version that does not support per-stream state - LOGGER.info("Setting source connector to pre-per-stream state version {}...", - AirbyteAcceptanceTestHarness.POSTGRES_SOURCE_LEGACY_CONNECTOR_VERSION); - testHarness.updateSourceDefinitionVersion(sourceDefinitionId, AirbyteAcceptanceTestHarness.POSTGRES_SOURCE_LEGACY_CONNECTOR_VERSION); - - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(SyncMode.INCREMENTAL) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(DestinationSyncMode.APPEND)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - LOGGER.info("Beginning {} sync 1", testInfo.getDisplayName()); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - LOGGER.info(STATE_AFTER_SYNC_ONE, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - - // Set source to a version that supports per-stream state - testHarness.updateSourceDefinitionVersion(sourceDefinitionId, currentSourceDefintionVersion); - LOGGER.info("Upgraded source connector per-stream state supported version {}.", currentSourceDefintionVersion); - - // sync one more time. verify that nothing has been synced - LOGGER.info("Starting {} sync 2", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead2 = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - LOGGER.info(STATE_AFTER_SYNC_TWO, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - final JobInfoRead syncJob = apiClient.getJobsApi().getJobInfo(new JobIdRequestBody().id(connectionSyncRead2.getJob().getId())); - final Optional result = syncJob.getAttempts().stream() - .sorted((a, b) -> Long.compare(b.getAttempt().getEndedAt(), a.getAttempt().getEndedAt())) - .findFirst(); - - assertTrue(result.isPresent()); - assertEquals(0, result.get().getAttempt().getRecordsSynced()); - assertEquals(0, result.get().getAttempt().getTotalStats().getRecordsEmitted()); - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - } - - @Test - void testResetAllWhenSchemaIsModifiedForLegacySource() throws Exception { - final String sourceTable1 = "test_table1"; - final String sourceTable2 = "test_table2"; - final String sourceTable3 = "test_table3"; - final String outputPrefix = "output_namespace_public.output_table_"; - final Database sourceDb = testHarness.getSourceDatabase(); - final Database destDb = testHarness.getDestinationDatabase(); - sourceDb.query(ctx -> { - ctx.createTableIfNotExists(sourceTable1).columns(DSL.field(NAME, SQLDataType.VARCHAR)).execute(); - ctx.truncate(sourceTable1).execute(); - ctx.insertInto(DSL.table(sourceTable1)).columns(DSL.field(NAME)).values("john").execute(); - ctx.insertInto(DSL.table(sourceTable1)).columns(DSL.field(NAME)).values("bob").execute(); - - ctx.createTableIfNotExists(sourceTable2).columns(DSL.field(VALUE, SQLDataType.VARCHAR)).execute(); - ctx.truncate(sourceTable2).execute(); - ctx.insertInto(DSL.table(sourceTable2)).columns(DSL.field(VALUE)).values("v1").execute(); - ctx.insertInto(DSL.table(sourceTable2)).columns(DSL.field(VALUE)).values("v2").execute(); - return null; - }); - - final SourceRead source = testHarness.createPostgresSource(true); - final UUID sourceId = source.getSourceId(); - final UUID sourceDefinitionId = source.getSourceDefinitionId(); - - // Fetch the current/most recent source definition version - final SourceDefinitionRead sourceDefinitionRead = - apiClient.getSourceDefinitionApi().getSourceDefinition(new SourceDefinitionIdRequestBody().sourceDefinitionId(sourceDefinitionId)); - final String currentSourceDefinitionVersion = sourceDefinitionRead.getDockerImageTag(); - - try { - // Set the source to a version that does not support per-stream state - LOGGER.info("Setting source connector to pre-per-stream state version {}...", - AirbyteAcceptanceTestHarness.POSTGRES_SOURCE_LEGACY_CONNECTOR_VERSION); - testHarness.updateSourceDefinitionVersion(sourceDefinitionId, AirbyteAcceptanceTestHarness.POSTGRES_SOURCE_LEGACY_CONNECTOR_VERSION); - - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final UUID destinationId = testHarness.createPostgresDestination(true).getDestinationId(); - final OperationRead operation = testHarness.createOperation(); - final String name = "test_reset_when_schema_is_modified_" + UUID.randomUUID(); - - LOGGER.info("Discovered catalog: {}", catalog); - - final ConnectionRead connection = - testHarness.createConnection(name, sourceId, destinationId, List.of(operation.getOperationId()), catalog, ConnectionScheduleType.MANUAL, - null); - LOGGER.info("Created Connection: {}", connection); - - sourceDb.query(ctx -> { - prettyPrintTables(ctx, sourceTable1, sourceTable2); - return null; - }); - - // Run initial sync - LOGGER.info("Running initial sync"); - final JobInfoRead syncRead = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connection.getConnectionId())); - waitForSuccessfulJob(apiClient.getJobsApi(), syncRead.getJob()); - - // Some inspection for debug - destDb.query(ctx -> { - prettyPrintTables(ctx, outputPrefix + sourceTable1, outputPrefix + sourceTable2); - return null; - }); - final ConnectionState initSyncState = - apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connection.getConnectionId())); - LOGGER.info("ConnectionState after the initial sync: " + initSyncState.toString()); - - testHarness.assertSourceAndDestinationDbInSync(false); - - // Patch some data in the source - LOGGER.info("Modifying source tables"); - sourceDb.query(ctx -> { - // Adding a new rows to make sure we sync more data. - ctx.insertInto(DSL.table(sourceTable1)).columns(DSL.field(NAME)).values("alice").execute(); - ctx.insertInto(DSL.table(sourceTable2)).columns(DSL.field(VALUE)).values("v3").execute(); - - // The removed rows should no longer be in the destination since we expect a full reset - ctx.deleteFrom(DSL.table(sourceTable1)).where(DSL.field(NAME).eq("john")).execute(); - ctx.deleteFrom(DSL.table(sourceTable2)).where(DSL.field(VALUE).eq("v2")).execute(); - - // Adding a new table to trigger reset from the update connection API - ctx.createTableIfNotExists(sourceTable3).columns(DSL.field(LOCATION, SQLDataType.VARCHAR)).execute(); - ctx.truncate(sourceTable3).execute(); - ctx.insertInto(DSL.table(sourceTable3)).columns(DSL.field(LOCATION)).values("home").execute(); - ctx.insertInto(DSL.table(sourceTable3)).columns(DSL.field(LOCATION)).values("work").execute(); - ctx.insertInto(DSL.table(sourceTable3)).columns(DSL.field(LOCATION)).values("space").execute(); - return null; - }); - - final AirbyteCatalog updatedCatalog = testHarness.discoverSourceSchemaWithoutCache(sourceId); - LOGGER.info("Discovered updated catalog: {}", updatedCatalog); - - // Update with refreshed catalog - LOGGER.info("Submit the update request"); - final WebBackendConnectionUpdate update = new WebBackendConnectionUpdate() - .connectionId(connection.getConnectionId()) - .syncCatalog(updatedCatalog); - webBackendApi.webBackendUpdateConnection(update); - - LOGGER.info("Inspecting Destination DB after the update request, tables should be empty"); - destDb.query(ctx -> { - prettyPrintTables(ctx, outputPrefix + sourceTable1, outputPrefix + sourceTable2); - return null; - }); - final ConnectionState postResetState = - apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connection.getConnectionId())); - LOGGER.info("ConnectionState after the update request: {}", postResetState.toString()); - - // Wait until the sync from the UpdateConnection is finished - final JobRead syncFromTheUpdate = testHarness.waitUntilTheNextJobIsStarted(connection.getConnectionId()); - LOGGER.info("Generated SyncJob config: {}", syncFromTheUpdate.toString()); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - final ConnectionState postUpdateState = - apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connection.getConnectionId())); - LOGGER.info("ConnectionState after the final sync: {}", postUpdateState.toString()); - - LOGGER.info("Inspecting DBs After the final sync"); - sourceDb.query(ctx -> { - prettyPrintTables(ctx, sourceTable1, sourceTable2, sourceTable3); - return null; - }); - destDb.query(ctx -> { - prettyPrintTables(ctx, outputPrefix + sourceTable1, outputPrefix + sourceTable2, outputPrefix + sourceTable3); - return null; - }); - - testHarness.assertSourceAndDestinationDbInSync(false); - } finally { - // Set source back to version it was set to at beginning of test - LOGGER.info("Set source connector back to per-stream state supported version {}.", currentSourceDefinitionVersion); - testHarness.updateSourceDefinitionVersion(sourceDefinitionId, currentSourceDefinitionVersion); - } - } - - private void prettyPrintTables(final DSLContext ctx, final String... tables) { - for (final String table : tables) { - LOGGER.info("select * from {}", table); - Arrays.stream(ctx.selectFrom(table) - .fetch() - .toString() - .split("\\n")).forEach(LOGGER::info); - } - } - - @Test - @Disabled - void testIncrementalSyncMultipleStreams() throws Exception { - LOGGER.info("Starting testIncrementalSyncMultipleStreams()"); - - PostgreSQLContainerHelper.runSqlScript(MountableFile.forClasspathResource("postgres_second_schema_multiple_tables.sql"), sourcePsql); - - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - for (final AirbyteStreamAndConfiguration streamAndConfig : catalog.getStreams()) { - final AirbyteStream stream = streamAndConfig.getStream(); - assertEquals(Lists.newArrayList(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL), stream.getSupportedSyncModes()); - // instead of assertFalse to avoid NPE from unboxed. - assertNull(stream.getSourceDefinedCursor()); - assertTrue(stream.getDefaultCursorField().isEmpty()); - assertTrue(stream.getSourceDefinedPrimaryKey().isEmpty()); - } - - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - LOGGER.info("Beginning testIncrementalSync() sync 1"); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - LOGGER.info(STATE_AFTER_SYNC_ONE, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - - // add new records and run again. - final Database source = testHarness.getSourceDatabase(); - // get contents of source before mutating records. - final List expectedRecordsIdAndName = testHarness.retrieveSourceRecords(source, STREAM_NAME); - final List expectedRecordsCoolEmployees = - testHarness.retrieveSourceRecords(source, STAGING_SCHEMA_NAME + "." + COOL_EMPLOYEES_TABLE_NAME); - final List expectedRecordsAwesomePeople = - testHarness.retrieveSourceRecords(source, STAGING_SCHEMA_NAME + "." + AWESOME_PEOPLE_TABLE_NAME); - expectedRecordsIdAndName.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, GERALT).build())); - expectedRecordsCoolEmployees.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, GERALT).build())); - expectedRecordsAwesomePeople.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 3).put(COLUMN_NAME, GERALT).build())); - // add a new record to each table - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(6, 'geralt')")); - source.query(ctx -> ctx.execute("INSERT INTO staging.cool_employees(id, name) VALUES(6, 'geralt')")); - source.query(ctx -> ctx.execute("INSERT INTO staging.awesome_people(id, name) VALUES(3, 'geralt')")); - // mutate a record that was already synced with out updating its cursor value. if we are actually - // full refreshing, this record will appear in the output and cause the test to fail. if we are, - // correctly, doing incremental, we will not find this value in the destination. - source.query(ctx -> ctx.execute("UPDATE id_and_name SET name='yennefer' WHERE id=2")); - source.query(ctx -> ctx.execute("UPDATE staging.cool_employees SET name='yennefer' WHERE id=2")); - source.query(ctx -> ctx.execute("UPDATE staging.awesome_people SET name='yennefer' WHERE id=2")); - - LOGGER.info("Starting testIncrementalSync() sync 2"); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - LOGGER.info(STATE_AFTER_SYNC_TWO, apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertRawDestinationContains(expectedRecordsIdAndName, new SchemaTableNamePair(PUBLIC_SCHEMA_NAME, STREAM_NAME)); - testHarness.assertRawDestinationContains(expectedRecordsCoolEmployees, new SchemaTableNamePair(STAGING_SCHEMA_NAME, COOL_EMPLOYEES_TABLE_NAME)); - testHarness.assertRawDestinationContains(expectedRecordsAwesomePeople, new SchemaTableNamePair(STAGING_SCHEMA_NAME, AWESOME_PEOPLE_TABLE_NAME)); - - // reset back to no data. - - LOGGER.info("Starting testIncrementalSync() reset"); - final JobInfoRead jobInfoRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitWhileJobHasStatus(apiClient.getJobsApi(), jobInfoRead.getJob(), - Sets.newHashSet(JobStatus.PENDING, JobStatus.RUNNING, JobStatus.INCOMPLETE, JobStatus.FAILED)); - // This is a band-aid to prevent some race conditions where the job status was updated but we may - // still be cleaning up some data in the reset table. This would be an argument for reworking the - // source of truth of the replication workflow state to be in DB rather than in Memory and - // serialized automagically by temporal - waitWhileJobIsRunning(apiClient.getJobsApi(), jobInfoRead.getJob(), Duration.ofMinutes(1)); - - LOGGER.info("state after reset: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertRawDestinationContains(Collections.emptyList(), new SchemaTableNamePair(PUBLIC, - STREAM_NAME)); - - // sync one more time. verify it is the equivalent of a full refresh. - LOGGER.info("Starting testIncrementalSync() sync 3"); - final JobInfoRead connectionSyncRead3 = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead3.getJob()); - LOGGER.info("state after sync 3: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - - } - - @Test - void testMultipleSchemasAndTablesSyncAndReset() throws Exception { - // create tables in another schema - PostgreSQLContainerHelper.runSqlScript(MountableFile.forClasspathResource("postgres_second_schema_multiple_tables.sql"), sourcePsql); - - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead.getJob()); - testHarness.assertSourceAndDestinationDbInSync(false); - final JobInfoRead connectionResetRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionResetRead.getJob()); - testHarness.assertDestinationDbEmpty(false); - } - - @Test - void testPartialResetResetAllWhenSchemaIsModified(final TestInfo testInfo) throws Exception { - LOGGER.info("Running: " + testInfo.getDisplayName()); - - // Add Table - final String additionalTable = "additional_table"; - final Database sourceDb = testHarness.getSourceDatabase(); - sourceDb.query(ctx -> { - ctx.createTableIfNotExists(additionalTable) - .columns(DSL.field("id", SQLDataType.INTEGER), DSL.field(FIELD, SQLDataType.VARCHAR)).execute(); - ctx.truncate(additionalTable).execute(); - ctx.insertInto(DSL.table(additionalTable)).columns(DSL.field("id"), DSL.field(FIELD)).values(1, "1").execute(); - ctx.insertInto(DSL.table(additionalTable)).columns(DSL.field("id"), DSL.field(FIELD)).values(2, "2").execute(); - return null; - }); - UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final OperationRead operation = testHarness.createOperation(); - final UUID operationId = operation.getOperationId(); - final String name = "test_reset_when_schema_is_modified_" + UUID.randomUUID(); - - testHarness.setIncrementalAppendSyncMode(catalog, List.of(COLUMN_ID)); - - final ConnectionRead connection = - testHarness.createConnection(name, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null); - - // Run initial sync - final JobInfoRead syncRead = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connection.getConnectionId())); - waitForSuccessfulJob(apiClient.getJobsApi(), syncRead.getJob()); - - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - assertStreamStateContainsStream(connection.getConnectionId(), List.of( - new StreamDescriptor().name(ID_AND_NAME).namespace(PUBLIC), - new StreamDescriptor().name(additionalTable).namespace(PUBLIC))); - - LOGGER.info("Initial sync ran, now running an update with a stream being removed."); - - /** - * Remove stream - */ - sourceDb.query(ctx -> ctx.dropTableIfExists(additionalTable).execute()); - - // Update with refreshed catalog - AirbyteCatalog refreshedCatalog = testHarness.discoverSourceSchemaWithoutCache(sourceId); - WebBackendConnectionUpdate update = testHarness.getUpdateInput(connection, refreshedCatalog, operation); - webBackendApi.webBackendUpdateConnection(update); - - // Wait until the sync from the UpdateConnection is finished - JobRead syncFromTheUpdate = waitUntilTheNextJobIsStarted(connection.getConnectionId()); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - // We do not check that the source and the dest are in sync here because removing a stream doesn't - // remove that - assertStreamStateContainsStream(connection.getConnectionId(), List.of( - new StreamDescriptor().name(ID_AND_NAME).namespace(PUBLIC))); - - LOGGER.info("Remove done, now running an update with a stream being added."); - - /** - * Add a stream -- the value of in the table are different than the initial import to ensure that it - * is properly reset. - */ - sourceDb.query(ctx -> { - ctx.createTableIfNotExists(additionalTable) - .columns(DSL.field("id", SQLDataType.INTEGER), DSL.field(FIELD, SQLDataType.VARCHAR)).execute(); - ctx.truncate(additionalTable).execute(); - ctx.insertInto(DSL.table(additionalTable)).columns(DSL.field("id"), DSL.field(FIELD)).values(3, "3").execute(); - ctx.insertInto(DSL.table(additionalTable)).columns(DSL.field("id"), DSL.field(FIELD)).values(4, "4").execute(); - return null; - }); - - sourceId = testHarness.createPostgresSource().getSourceId(); - refreshedCatalog = testHarness.discoverSourceSchema(sourceId); - update = testHarness.getUpdateInput(connection, refreshedCatalog, operation); - webBackendApi.webBackendUpdateConnection(update); - - syncFromTheUpdate = waitUntilTheNextJobIsStarted(connection.getConnectionId()); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - // We do not check that the source and the dest are in sync here because removing a stream doesn't - // remove that - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - assertStreamStateContainsStream(connection.getConnectionId(), List.of( - new StreamDescriptor().name(ID_AND_NAME).namespace(PUBLIC), - new StreamDescriptor().name(additionalTable).namespace(PUBLIC))); - - LOGGER.info("Addition done, now running an update with a stream being updated."); - - // Update - sourceDb.query(ctx -> { - ctx.dropTableIfExists(additionalTable).execute(); - ctx.createTableIfNotExists(additionalTable) - .columns(DSL.field("id", SQLDataType.INTEGER), DSL.field(FIELD, SQLDataType.VARCHAR), DSL.field("another_field", SQLDataType.VARCHAR)) - .execute(); - ctx.truncate(additionalTable).execute(); - ctx.insertInto(DSL.table(additionalTable)).columns(DSL.field("id"), DSL.field(FIELD), DSL.field("another_field")).values(3, "3", "three") - .execute(); - ctx.insertInto(DSL.table(additionalTable)).columns(DSL.field("id"), DSL.field(FIELD), DSL.field("another_field")).values(4, "4", "four") - .execute(); - return null; - }); - - sourceId = testHarness.createPostgresSource().getSourceId(); - refreshedCatalog = testHarness.discoverSourceSchema(sourceId); - update = testHarness.getUpdateInput(connection, refreshedCatalog, operation); - webBackendApi.webBackendUpdateConnection(update); - - syncFromTheUpdate = waitUntilTheNextJobIsStarted(connection.getConnectionId()); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - // We do not check that the source and the dest are in sync here because removing a stream doesn't - // remove that - testHarness.assertSourceAndDestinationDbInSync(WITHOUT_SCD_TABLE); - assertStreamStateContainsStream(connection.getConnectionId(), List.of( - new StreamDescriptor().name(ID_AND_NAME).namespace(PUBLIC), - new StreamDescriptor().name(additionalTable).namespace(PUBLIC))); - - } - - @Test - @Order(19) - void testIncrementalDedupeSyncRemoveOneColumn() throws Exception { - // !!! NOTE !!! this test relies on a feature flag that currently defaults to false. If you're - // running these tests locally against an external deployment and this test is failing, make sure - // the flag is enabled. - // Specifically: - // APPLY_FIELD_SELECTION=true - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND_DEDUP; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode) - .primaryKey(List.of(List.of(COLUMN_ID)))); - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - // sync from start - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - - testHarness.assertSourceAndDestinationDbInSync(WITH_SCD_TABLE); - - // Update the catalog, so we only select the id column. - catalog.getStreams().get(0).getConfig().fieldSelectionEnabled(true).addSelectedFieldsItem(new SelectedFieldInfo().addFieldPathItem("id")); - testHarness.updateConnectionCatalog(connectionId, catalog); - - // add new records and run again. - final Database source = testHarness.getSourceDatabase(); - final List expectedRawRecords = testHarness.retrieveSourceRecords(source, STREAM_NAME); - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(6, 'mike')")); - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(7, 'chris')")); - // The expected new raw records should only have the ID column. - expectedRawRecords.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).build())); - expectedRawRecords.add(Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 7).build())); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - - // For the normalized records, they should all only have the ID column. - final List expectedNormalizedRecords = testHarness.retrieveSourceRecords(source, STREAM_NAME).stream() - .map((record) -> ((ObjectNode) record).retain(COLUMN_ID)).collect(Collectors.toList()); - - testHarness.assertRawDestinationContains(expectedRawRecords, new SchemaTableNamePair(PUBLIC, STREAM_NAME)); - testHarness.assertNormalizedDestinationContainsIdColumn(expectedNormalizedRecords); - } - - private void assertStreamStateContainsStream(final UUID connectionId, final List expectedStreamDescriptors) throws ApiException { - final ConnectionState state = apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId)); - final List streamDescriptors = state.getStreamState().stream().map(StreamState::getStreamDescriptor).toList(); - - Assertions.assertTrue(streamDescriptors.containsAll(expectedStreamDescriptors) && expectedStreamDescriptors.containsAll(streamDescriptors)); - } - - private JobRead getMostRecentSyncJobId(final UUID connectionId) throws Exception { - return apiClient.getJobsApi() - .listJobsFor(new JobListRequestBody().configId(connectionId.toString()).configTypes(List.of(JobConfigType.SYNC))) - .getJobs() - .stream().findFirst().map(JobWithAttemptsRead::getJob).orElseThrow(); - } - - private JobRead waitUntilTheNextJobIsStarted(final UUID connectionId) throws Exception { - final JobRead lastJob = getMostRecentSyncJobId(connectionId); - if (lastJob.getStatus() != JobStatus.SUCCEEDED) { - return lastJob; - } - - JobRead mostRecentSyncJob = getMostRecentSyncJobId(connectionId); - while (mostRecentSyncJob.getId().equals(lastJob.getId())) { - Thread.sleep(Duration.ofSeconds(10).toMillis()); - mostRecentSyncJob = getMostRecentSyncJobId(connectionId); - } - return mostRecentSyncJob; - } - - /** - * Waits for the given connection to finish, waiting at 30s intervals, until maxRetries is reached. - * - * @param connectionId the connection to wait for - * @param maxRetries the number of times to retry - * @throws InterruptedException - */ - private void waitForSuccessfulJobWithRetries(final UUID connectionId, final int maxRetries) throws InterruptedException { - int i; - for (i = 0; i < maxRetries; i++) { - try { - final JobRead jobInfo = testHarness.getMostRecentSyncJobId(connectionId); - waitForSuccessfulJob(apiClient.getJobsApi(), jobInfo); - break; - } catch (final Exception e) { - LOGGER.info("Something went wrong querying jobs API, retrying..."); - } - sleep(Duration.ofSeconds(30).toMillis()); - } - - if (i == maxRetries) { - LOGGER.error("Sync job did not complete within 5 minutes"); - } - } - - // This test is disabled because it takes a couple of minutes to run, as it is testing timeouts. - // It should be re-enabled when the @SlowIntegrationTest can be applied to it. - // See relevant issue: https://github.com/airbytehq/airbyte/issues/8397 - @Test - @Disabled - void testFailureTimeout() throws Exception { - final SourceDefinitionRead sourceDefinition = testHarness.createE2eSourceDefinition(workspaceId); - final DestinationDefinitionRead destinationDefinition = testHarness.createE2eDestinationDefinition(workspaceId); - - final SourceRead source = testHarness.createSource( - E2E_TEST_SOURCE + UUID.randomUUID(), - workspaceId, - sourceDefinition.getSourceDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, INFINITE_FEED) - .put(MAX_RECORDS, 1000) - .put(MESSAGE_INTERVAL, 100) - .build())); - - // Destination fails after processing 5 messages, so the job should fail after the graceful close - // timeout of 1 minute - final DestinationRead destination = testHarness.createDestination( - "E2E Test Destination -" + UUID.randomUUID(), - workspaceId, - destinationDefinition.getDestinationDefinitionId(), - Jsons.jsonNode(ImmutableMap.builder() - .put(TYPE, "FAILING") - .put("num_messages", 5) - .build())); - - final UUID sourceId = source.getSourceId(); - final UUID destinationId = destination.getDestinationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - - final UUID connectionId = - testHarness.createConnection(TEST_CONNECTION, sourceId, destinationId, Collections.emptyList(), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - // wait to get out of pending. - final JobRead runningJob = - waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead1.getJob(), Sets.newHashSet(JobStatus.PENDING)); - - // wait for job for max of 3 minutes, by which time the job attempt should have failed - waitWhileJobHasStatus(apiClient.getJobsApi(), runningJob, Sets.newHashSet(JobStatus.RUNNING), Duration.ofMinutes(3)); - - final JobIdRequestBody jobId = new JobIdRequestBody().id(runningJob.getId()); - final JobInfoRead jobInfo = apiClient.getJobsApi().getJobInfo(jobId); - final AttemptInfoRead attemptInfoRead = jobInfo.getAttempts().get(jobInfo.getAttempts().size() - 1); - - // assert that the job attempt failed, and cancel the job regardless of status to prevent retries - try { - assertEquals(AttemptStatus.FAILED, attemptInfoRead.getAttempt().getStatus()); - } finally { - apiClient.getJobsApi().cancelJob(jobId); - } - } - -} diff --git a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/CdcAcceptanceTests.java b/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/CdcAcceptanceTests.java deleted file mode 100644 index 57a5435ba57ba..0000000000000 --- a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/CdcAcceptanceTests.java +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.acceptance; - -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.COLUMN_ID; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.COLUMN_NAME; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitForSuccessfulJob; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import com.fasterxml.jackson.databind.JsonNode; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import io.airbyte.api.client.AirbyteApiClient; -import io.airbyte.api.client.generated.WebBackendApi; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.model.generated.AirbyteCatalog; -import io.airbyte.api.client.model.generated.AirbyteStream; -import io.airbyte.api.client.model.generated.AirbyteStreamAndConfiguration; -import io.airbyte.api.client.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.client.model.generated.ConnectionRead; -import io.airbyte.api.client.model.generated.ConnectionScheduleType; -import io.airbyte.api.client.model.generated.ConnectionState; -import io.airbyte.api.client.model.generated.ConnectionStateType; -import io.airbyte.api.client.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.DestinationDefinitionRead; -import io.airbyte.api.client.model.generated.DestinationSyncMode; -import io.airbyte.api.client.model.generated.JobInfoRead; -import io.airbyte.api.client.model.generated.JobRead; -import io.airbyte.api.client.model.generated.OperationRead; -import io.airbyte.api.client.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.SourceDefinitionRead; -import io.airbyte.api.client.model.generated.SourceRead; -import io.airbyte.api.client.model.generated.StreamDescriptor; -import io.airbyte.api.client.model.generated.StreamState; -import io.airbyte.api.client.model.generated.SyncMode; -import io.airbyte.api.client.model.generated.WebBackendConnectionUpdate; -import io.airbyte.commons.json.Jsons; -import io.airbyte.db.Database; -import io.airbyte.test.utils.AirbyteAcceptanceTestHarness; -import io.airbyte.test.utils.SchemaTableNamePair; -import java.io.IOException; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import org.jooq.Record; -import org.jooq.Result; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * These tests test the CDC source behavior in Airbyte, ensuring that the behavior of syncs when in - * CDC mode is as expected - *

- * Some of the tests in this class are specifically testing partial reset behavior when in CDC mode, - * support for which was recently added to the postgres connector. - *

- * These tests are disabled in Kube, similar to the BasicAcceptanceTests, because they aren't - * testing any behavior that is specific to or dependent on this being run on kube vs docker. - * Therefore, since operations tend to take longer to perform on kube, there is little value in - * re-running these tests on kube when we already run them on docker. - */ -@DisabledIfEnvironmentVariable(named = "KUBE", - matches = "true") -@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") -class CdcAcceptanceTests { - - record DestinationCdcRecordMatcher(JsonNode sourceRecord, Instant minUpdatedAt, Optional minDeletedAt) { - - } - - private static final Logger LOGGER = LoggerFactory.getLogger(BasicAcceptanceTests.class); - - private static final String POSTGRES_INIT_SQL_FILE = "postgres_init_cdc.sql"; - private static final String CDC_METHOD = "CDC"; - // must match replication slot name used in the above POSTGRES_INIT_SQL_FILE - private static final String REPLICATION_SLOT = "airbyte_slot"; - // must match publication name used in the above POSTGRES_INIT_SQL_FILE - private static final String PUBLICATION = "airbyte_publication"; - private static final Integer INITIAL_WAITING_SECONDS = 5; - - private static final String SOURCE_NAME = "CDC Source"; - private static final String CONNECTION_NAME = "test-connection"; - private static final String SCHEMA_NAME = "public"; - private static final String CDC_UPDATED_AT_COLUMN = "_ab_cdc_updated_at"; - private static final String CDC_DELETED_AT_COLUMN = "_ab_cdc_deleted_at"; - private static final String ID_AND_NAME_TABLE = "id_and_name"; - private static final String COLOR_PALETTE_TABLE = "color_palette"; - private static final String COLUMN_COLOR = "color"; - private static final String STARTING = "Starting {}"; - private static final String STARTING_SYNC_ONE = "Starting {} sync 1"; - - // version of the postgres destination connector that was built with the - // old Airbyte protocol that does not contain any per-stream logic/fields - private static final String POSTGRES_DESTINATION_LEGACY_CONNECTOR_VERSION = "0.3.19"; - - private static AirbyteApiClient apiClient; - private static WebBackendApi webBackendApi; - private static UUID workspaceId; - private static OperationRead operationRead; - - private AirbyteAcceptanceTestHarness testHarness; - - @BeforeAll - static void init() throws URISyntaxException, IOException, InterruptedException, ApiException { - apiClient = new AirbyteApiClient( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - webBackendApi = new WebBackendApi( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - // work in whatever default workspace is present. - workspaceId = apiClient.getWorkspaceApi().listWorkspaces().getWorkspaces().get(0).getWorkspaceId(); - LOGGER.info("workspaceId = " + workspaceId); - - // log which connectors are being used. - final SourceDefinitionRead sourceDef = apiClient.getSourceDefinitionApi() - .getSourceDefinition(new SourceDefinitionIdRequestBody() - .sourceDefinitionId(UUID.fromString("decd338e-5647-4c0b-adf4-da0e75f5a750"))); - final DestinationDefinitionRead destinationDef = apiClient.getDestinationDefinitionApi() - .getDestinationDefinition(new DestinationDefinitionIdRequestBody() - .destinationDefinitionId(UUID.fromString("25c5221d-dce2-4163-ade9-739ef790f503"))); - LOGGER.info("pg source definition: {}", sourceDef.getDockerImageTag()); - LOGGER.info("pg destination definition: {}", destinationDef.getDockerImageTag()); - } - - @BeforeEach - void setup() throws URISyntaxException, IOException, InterruptedException, ApiException, SQLException { - testHarness = new AirbyteAcceptanceTestHarness(apiClient, workspaceId, POSTGRES_INIT_SQL_FILE); - testHarness.setup(); - } - - @AfterEach - void end() { - testHarness.cleanup(); - testHarness.stopDbAndContainers(); - } - - @Test - void testIncrementalCdcSync(final TestInfo testInfo) throws Exception { - LOGGER.info(STARTING, testInfo.getDisplayName()); - - final UUID connectionId = createCdcConnection(); - LOGGER.info(STARTING_SYNC_ONE, testInfo.getDisplayName()); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - LOGGER.info("state after sync 1: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - final Database source = testHarness.getSourceDatabase(); - - List expectedIdAndNameRecords = getCdcRecordMatchersFromSource(source, ID_AND_NAME_TABLE); - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - - List expectedColorPaletteRecords = getCdcRecordMatchersFromSource(source, COLOR_PALETTE_TABLE); - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - - final List expectedStreams = List.of( - new StreamDescriptor().namespace(SCHEMA_NAME).name(ID_AND_NAME_TABLE), - new StreamDescriptor().namespace(SCHEMA_NAME).name(COLOR_PALETTE_TABLE)); - assertGlobalStateContainsStreams(connectionId, expectedStreams); - - final Instant beforeFirstUpdate = Instant.now(); - - LOGGER.info("Inserting and updating source db records"); - // add new records and run again. - // add a new record - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(6, 'geralt')")); - // mutate a record that was already synced with out updating its cursor value. - // since this is a CDC connection, the destination should contain a record with this - // new value and an updated_at time corresponding to this update query - source.query(ctx -> ctx.execute("UPDATE id_and_name SET name='yennefer' WHERE id=2")); - expectedIdAndNameRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, "geralt").build()), - beforeFirstUpdate, - Optional.empty())); - expectedIdAndNameRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 2).put(COLUMN_NAME, "yennefer").build()), - beforeFirstUpdate, - Optional.empty())); - - // do the same for the other table - source.query(ctx -> ctx.execute("INSERT INTO color_palette(id, color) VALUES(4, 'yellow')")); - source.query(ctx -> ctx.execute("UPDATE color_palette SET color='purple' WHERE id=2")); - expectedColorPaletteRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 4).put(COLUMN_COLOR, "yellow").build()), - beforeFirstUpdate, - Optional.empty())); - expectedColorPaletteRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 2).put(COLUMN_COLOR, "purple").build()), - beforeFirstUpdate, - Optional.empty())); - - LOGGER.info("Starting {} sync 2", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - LOGGER.info("state after sync 2: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - assertGlobalStateContainsStreams(connectionId, expectedStreams); - - // reset back to no data. - - LOGGER.info("Starting {} reset", testInfo.getDisplayName()); - final JobInfoRead jobInfoRead = apiClient.getConnectionApi().resetConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), jobInfoRead.getJob()); - - LOGGER.info("state after reset: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - assertDestinationMatches(ID_AND_NAME_TABLE, Collections.emptyList()); - assertDestinationMatches(COLOR_PALETTE_TABLE, Collections.emptyList()); - assertNoState(connectionId); - - // sync one more time. verify it is the equivalent of a full refresh. - LOGGER.info("Starting {} sync 3", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead3 = - apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead3.getJob()); - LOGGER.info("state after sync 3: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - expectedIdAndNameRecords = getCdcRecordMatchersFromSource(source, ID_AND_NAME_TABLE); - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - - expectedColorPaletteRecords = getCdcRecordMatchersFromSource(source, COLOR_PALETTE_TABLE); - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - - assertGlobalStateContainsStreams(connectionId, expectedStreams); - } - - // tests that incremental syncs still work properly even when using a destination connector that was - // built on the old protocol that did not have any per-stream state fields - @Test - void testIncrementalCdcSyncWithLegacyDestinationConnector(final TestInfo testInfo) throws Exception { - LOGGER.info(STARTING, testInfo.getDisplayName()); - final UUID postgresDestDefId = testHarness.getPostgresDestinationDefinitionId(); - // Fetch the current/most recent source definition version - final DestinationDefinitionRead destinationDefinitionRead = apiClient.getDestinationDefinitionApi().getDestinationDefinition( - new DestinationDefinitionIdRequestBody().destinationDefinitionId(postgresDestDefId)); - LOGGER.info("Current postgres destination definition version: {}", destinationDefinitionRead.getDockerImageTag()); - - try { - LOGGER.info("Setting postgres destination definition to version {}", POSTGRES_DESTINATION_LEGACY_CONNECTOR_VERSION); - testHarness.updateDestinationDefinitionVersion(postgresDestDefId, POSTGRES_DESTINATION_LEGACY_CONNECTOR_VERSION); - - testIncrementalCdcSync(testInfo); - } finally { - // set postgres destination definition back to latest version for other tests - LOGGER.info("Setting postgres destination definition back to version {}", destinationDefinitionRead.getDockerImageTag()); - testHarness.updateDestinationDefinitionVersion(postgresDestDefId, destinationDefinitionRead.getDockerImageTag()); - } - } - - @Test - void testDeleteRecordCdcSync(final TestInfo testInfo) throws Exception { - LOGGER.info(STARTING, testInfo.getDisplayName()); - - final UUID connectionId = createCdcConnection(); - LOGGER.info(STARTING_SYNC_ONE, testInfo.getDisplayName()); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - LOGGER.info("state after sync 1: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - final Database source = testHarness.getSourceDatabase(); - final List expectedIdAndNameRecords = getCdcRecordMatchersFromSource(source, ID_AND_NAME_TABLE); - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - - final Instant beforeDelete = Instant.now(); - - LOGGER.info("Deleting record"); - // delete a record - source.query(ctx -> ctx.execute("DELETE FROM id_and_name WHERE id=1")); - - final Map deletedRecordMap = new HashMap<>(); - deletedRecordMap.put(COLUMN_ID, 1); - deletedRecordMap.put(COLUMN_NAME, null); - expectedIdAndNameRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(deletedRecordMap), - beforeDelete, - Optional.of(beforeDelete))); - - LOGGER.info("Starting {} sync 2", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - LOGGER.info("state after sync 2: {}", apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId))); - - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - } - - @Test - void testPartialResetFromSchemaUpdate(final TestInfo testInfo) throws Exception { - LOGGER.info(STARTING, testInfo.getDisplayName()); - - final UUID connectionId = createCdcConnection(); - LOGGER.info(STARTING_SYNC_ONE, testInfo.getDisplayName()); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - - final Database source = testHarness.getSourceDatabase(); - - final List expectedIdAndNameRecords = getCdcRecordMatchersFromSource(source, ID_AND_NAME_TABLE); - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - - final List expectedColorPaletteRecords = getCdcRecordMatchersFromSource(source, COLOR_PALETTE_TABLE); - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - - final StreamDescriptor idAndNameStreamDescriptor = new StreamDescriptor().namespace(SCHEMA_NAME).name(ID_AND_NAME_TABLE); - final StreamDescriptor colorPaletteStreamDescriptor = new StreamDescriptor().namespace(SCHEMA_NAME).name(COLOR_PALETTE_TABLE); - assertGlobalStateContainsStreams(connectionId, List.of(idAndNameStreamDescriptor, colorPaletteStreamDescriptor)); - - LOGGER.info("Removing color palette table"); - source.query(ctx -> ctx.dropTable(COLOR_PALETTE_TABLE).execute()); - - LOGGER.info("Refreshing schema and updating connection"); - final ConnectionRead connectionRead = apiClient.getConnectionApi().getConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - final UUID sourceId = createCdcSource().getSourceId(); - final AirbyteCatalog refreshedCatalog = testHarness.discoverSourceSchema(sourceId); - LOGGER.info("Refreshed catalog: {}", refreshedCatalog); - final WebBackendConnectionUpdate update = testHarness.getUpdateInput(connectionRead, refreshedCatalog, operationRead); - webBackendApi.webBackendUpdateConnection(update); - - LOGGER.info("Waiting for sync job after update to complete"); - final JobRead syncFromTheUpdate = testHarness.waitUntilTheNextJobIsStarted(connectionId); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - // We do not check that the source and the dest are in sync here because removing a stream doesn't - // delete its data in the destination - assertGlobalStateContainsStreams(connectionId, List.of(idAndNameStreamDescriptor)); - } - - @Test - void testPartialResetFromStreamSelection(final TestInfo testInfo) throws Exception { - LOGGER.info(STARTING, testInfo.getDisplayName()); - - final UUID connectionId = createCdcConnection(); - LOGGER.info(STARTING_SYNC_ONE, testInfo.getDisplayName()); - - final JobInfoRead connectionSyncRead1 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead1.getJob()); - - final Database source = testHarness.getSourceDatabase(); - - final List expectedIdAndNameRecords = getCdcRecordMatchersFromSource(source, ID_AND_NAME_TABLE); - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - - final List expectedColorPaletteRecords = getCdcRecordMatchersFromSource(source, COLOR_PALETTE_TABLE); - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - - final StreamDescriptor idAndNameStreamDescriptor = new StreamDescriptor().namespace(SCHEMA_NAME).name(ID_AND_NAME_TABLE); - final StreamDescriptor colorPaletteStreamDescriptor = new StreamDescriptor().namespace(SCHEMA_NAME).name(COLOR_PALETTE_TABLE); - assertGlobalStateContainsStreams(connectionId, List.of(idAndNameStreamDescriptor, colorPaletteStreamDescriptor)); - - LOGGER.info("Removing color palette stream from configured catalog"); - final ConnectionRead connectionRead = apiClient.getConnectionApi().getConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - final UUID sourceId = connectionRead.getSourceId(); - AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final List streams = catalog.getStreams(); - // filter out color_palette stream - final List updatedStreams = streams - .stream() - .filter(stream -> !COLOR_PALETTE_TABLE.equals(stream.getStream().getName())) - .toList(); - catalog.setStreams(updatedStreams); - LOGGER.info("Updated catalog: {}", catalog); - WebBackendConnectionUpdate update = testHarness.getUpdateInput(connectionRead, catalog, operationRead); - webBackendApi.webBackendUpdateConnection(update); - - LOGGER.info("Waiting for sync job after update to start"); - JobRead syncFromTheUpdate = testHarness.waitUntilTheNextJobIsStarted(connectionId); - LOGGER.info("Waiting for sync job after update to complete"); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - // We do not check that the source and the dest are in sync here because removing a stream doesn't - // delete its data in the destination - assertGlobalStateContainsStreams(connectionId, List.of(idAndNameStreamDescriptor)); - - LOGGER.info("Adding color palette stream back to configured catalog"); - catalog = testHarness.discoverSourceSchema(sourceId); - LOGGER.info("Updated catalog: {}", catalog); - update = testHarness.getUpdateInput(connectionRead, catalog, operationRead); - webBackendApi.webBackendUpdateConnection(update); - - LOGGER.info("Waiting for sync job after update to start"); - syncFromTheUpdate = testHarness.waitUntilTheNextJobIsStarted(connectionId); - LOGGER.info("Checking that id_and_name table is unaffected by the partial reset"); - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - LOGGER.info("Checking that color_palette table was cleared in the destination due to the reset triggered by the update"); - assertDestinationMatches(COLOR_PALETTE_TABLE, List.of()); - LOGGER.info("Waiting for sync job after update to complete"); - waitForSuccessfulJob(apiClient.getJobsApi(), syncFromTheUpdate); - - // Verify that color palette table records exist in destination again after sync. - // If we see 0 records for this table in the destination, that means the CDC partial reset logic is - // not working properly, and it continued from the replication log cursor for this stream despite - // this stream's state being reset - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - assertGlobalStateContainsStreams(connectionId, List.of(idAndNameStreamDescriptor, colorPaletteStreamDescriptor)); - - // Verify that incremental still works properly after partial reset - LOGGER.info("Adding new records to tables"); - final Instant beforeInsert = Instant.now(); - source.query(ctx -> ctx.execute("INSERT INTO id_and_name(id, name) VALUES(6, 'geralt')")); - expectedIdAndNameRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 6).put(COLUMN_NAME, "geralt").build()), - beforeInsert, - Optional.empty())); - - source.query(ctx -> ctx.execute("INSERT INTO color_palette(id, color) VALUES(4, 'yellow')")); - expectedColorPaletteRecords.add(new DestinationCdcRecordMatcher( - Jsons.jsonNode(ImmutableMap.builder().put(COLUMN_ID, 4).put(COLUMN_COLOR, "yellow").build()), - beforeInsert, - Optional.empty())); - - LOGGER.info("Starting {} sync after insert", testInfo.getDisplayName()); - final JobInfoRead connectionSyncRead2 = apiClient.getConnectionApi() - .syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead2.getJob()); - - assertDestinationMatches(ID_AND_NAME_TABLE, expectedIdAndNameRecords); - assertDestinationMatches(COLOR_PALETTE_TABLE, expectedColorPaletteRecords); - assertGlobalStateContainsStreams(connectionId, List.of(idAndNameStreamDescriptor, colorPaletteStreamDescriptor)); - } - - private List getCdcRecordMatchersFromSource(final Database source, final String tableName) throws SQLException { - final List sourceRecords = testHarness.retrieveSourceRecords(source, tableName); - return new ArrayList<>(sourceRecords - .stream() - .map(sourceRecord -> new DestinationCdcRecordMatcher(sourceRecord, Instant.EPOCH, Optional.empty())) - .toList()); - } - - private UUID createCdcConnection() throws ApiException { - final SourceRead sourceRead = createCdcSource(); - final UUID sourceId = sourceRead.getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - - operationRead = testHarness.createOperation(); - final UUID operationId = operationRead.getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final AirbyteStream stream = catalog.getStreams().get(0).getStream(); - LOGGER.info("stream: {}", stream); - - assertEquals(Lists.newArrayList(SyncMode.FULL_REFRESH, SyncMode.INCREMENTAL), stream.getSupportedSyncModes()); - assertTrue(stream.getSourceDefinedCursor()); - assertTrue(stream.getDefaultCursorField().isEmpty()); - assertEquals(List.of(List.of("id")), stream.getSourceDefinedPrimaryKey()); - - final SyncMode syncMode = SyncMode.INCREMENTAL; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.APPEND; - catalog.getStreams().forEach(s -> s.getConfig() - .syncMode(syncMode) - .cursorField(List.of(COLUMN_ID)) - .destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(CONNECTION_NAME, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - return connectionId; - } - - private SourceRead createCdcSource() throws ApiException { - final UUID postgresSourceDefinitionId = testHarness.getPostgresSourceDefinitionId(); - final JsonNode sourceDbConfig = testHarness.getSourceDbConfig(); - final Map sourceDbConfigMap = Jsons.object(sourceDbConfig, Map.class); - sourceDbConfigMap.put("is_test", true); - sourceDbConfigMap.put("replication_method", ImmutableMap.builder() - .put("method", CDC_METHOD) - .put("replication_slot", REPLICATION_SLOT) - .put("publication", PUBLICATION) - .put("initial_waiting_seconds", INITIAL_WAITING_SECONDS) - .build()); - LOGGER.info("final sourceDbConfigMap: {}", sourceDbConfigMap); - - return testHarness.createSource( - SOURCE_NAME, - workspaceId, - postgresSourceDefinitionId, - Jsons.jsonNode(sourceDbConfigMap)); - } - - @SuppressWarnings("PMD.AvoidLiteralsInIfCondition") - private void assertDestinationMatches(final String streamName, final List expectedDestRecordMatchers) - throws Exception { - final List destRecords = testHarness.retrieveRawDestinationRecords(new SchemaTableNamePair(SCHEMA_NAME, streamName)); - if (destRecords.size() != expectedDestRecordMatchers.size()) { - final String errorMessage = String.format( - "The number of destination records %d does not match the expected number %d", - destRecords.size(), - expectedDestRecordMatchers.size()); - LOGGER.error(errorMessage); - LOGGER.error("Expected dest record matchers: {}\nActual destination records: {}", expectedDestRecordMatchers, destRecords); - throw new IllegalStateException(errorMessage); - } - - for (final DestinationCdcRecordMatcher recordMatcher : expectedDestRecordMatchers) { - final List matchingDestRecords = destRecords.stream().filter(destRecord -> { - final Map sourceRecordMap = Jsons.object(recordMatcher.sourceRecord, Map.class); - final Map destRecordMap = Jsons.object(destRecord, Map.class); - - final boolean sourceRecordValuesMatch = sourceRecordMap.keySet() - .stream() - .allMatch(column -> Objects.equals(sourceRecordMap.get(column), destRecordMap.get(column))); - - final Object cdcUpdatedAtValue = destRecordMap.get(CDC_UPDATED_AT_COLUMN); - // use epoch millis to guarantee the two values are at the same precision - final boolean cdcUpdatedAtMatches = cdcUpdatedAtValue != null - && Instant.parse(String.valueOf(cdcUpdatedAtValue)).toEpochMilli() >= recordMatcher.minUpdatedAt.toEpochMilli(); - - final Object cdcDeletedAtValue = destRecordMap.get(CDC_DELETED_AT_COLUMN); - final boolean cdcDeletedAtMatches; - if (recordMatcher.minDeletedAt.isPresent()) { - cdcDeletedAtMatches = cdcDeletedAtValue != null - && Instant.parse(String.valueOf(cdcDeletedAtValue)).toEpochMilli() >= recordMatcher.minDeletedAt.get().toEpochMilli(); - } else { - cdcDeletedAtMatches = cdcDeletedAtValue == null; - } - - return sourceRecordValuesMatch && cdcUpdatedAtMatches && cdcDeletedAtMatches; - }).toList(); - - if (matchingDestRecords.isEmpty()) { - throw new IllegalStateException(String.format( - "Could not find a matching CDC destination record for record matcher %s. Destination records: %s", recordMatcher, destRecords)); - } - if (matchingDestRecords.size() > 1) { - throw new IllegalStateException(String.format( - "Expected only one matching CDC destination record for record matcher %s, but found multiple: %s", recordMatcher, matchingDestRecords)); - } - } - } - - private void assertGlobalStateContainsStreams(final UUID connectionId, final List expectedStreams) throws ApiException { - final ConnectionState state = apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId)); - LOGGER.info("state: {}", state); - assertEquals(ConnectionStateType.GLOBAL, state.getStateType()); - final List stateStreams = state.getGlobalState().getStreamStates().stream().map(StreamState::getStreamDescriptor).toList(); - - Assertions.assertTrue(stateStreams.containsAll(expectedStreams) && expectedStreams.containsAll(stateStreams), - String.format("Expected state to have streams %s, but it actually had streams %s", expectedStreams, stateStreams)); - } - - private void assertNoState(final UUID connectionId) throws ApiException { - final ConnectionState state = apiClient.getStateApi().getState(new ConnectionIdRequestBody().connectionId(connectionId)); - assertEquals(ConnectionStateType.NOT_SET, state.getStateType()); - assertNull(state.getState()); - assertNull(state.getStreamState()); - assertNull(state.getGlobalState()); - } - - // can be helpful for debugging - @SuppressWarnings("PMD.UnusedPrivateMethod") - private void printDbs() throws SQLException { - final Database sourceDb = testHarness.getSourceDatabase(); - Set pairs = testHarness.listAllTables(sourceDb); - LOGGER.info("Printing source tables"); - for (final SchemaTableNamePair pair : pairs) { - final Result result = sourceDb.query( - context -> context.fetch(String.format("SELECT * FROM %s.%s", pair.schemaName(), pair.tableName()))); - LOGGER.info("{}.{} contents:\n{}", pair.schemaName(), pair.tableName(), result); - } - - final Database destDb = testHarness.getDestinationDatabase(); - pairs = testHarness.listAllTables(destDb); - LOGGER.info("Printing destination tables"); - for (final SchemaTableNamePair pair : pairs) { - final Result result = destDb.query(context -> context.fetch(String.format("SELECT * FROM %s.%s", pair.schemaName(), pair.tableName()))); - LOGGER.info("{}.{} contents:\n{}", pair.schemaName(), pair.tableName(), result); - } - } - -} diff --git a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/ContainerOrchestratorAcceptanceTests.java b/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/ContainerOrchestratorAcceptanceTests.java deleted file mode 100644 index 7ed69814a6f15..0000000000000 --- a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/ContainerOrchestratorAcceptanceTests.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.acceptance; - -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitForSuccessfulJob; -import static io.airbyte.test.utils.AirbyteAcceptanceTestHarness.waitWhileJobHasStatus; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import io.airbyte.api.client.AirbyteApiClient; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.model.generated.AirbyteCatalog; -import io.airbyte.api.client.model.generated.ConnectionIdRequestBody; -import io.airbyte.api.client.model.generated.ConnectionScheduleType; -import io.airbyte.api.client.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.DestinationDefinitionRead; -import io.airbyte.api.client.model.generated.DestinationSyncMode; -import io.airbyte.api.client.model.generated.JobIdRequestBody; -import io.airbyte.api.client.model.generated.JobInfoRead; -import io.airbyte.api.client.model.generated.JobStatus; -import io.airbyte.api.client.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.SourceDefinitionRead; -import io.airbyte.api.client.model.generated.SyncMode; -import io.airbyte.test.utils.AirbyteAcceptanceTestHarness; -import io.fabric8.kubernetes.client.KubernetesClient; -import java.io.IOException; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; - -/** - * This class tests behavior that is specific to container-orchestrator deployments, such as scaling - * down and back up workers while a sync is running to ensure it is not affected by a deployment. - *

- * This test class is only enabled if the KUBE environment variable is true, because container - * orchestrators are currently only used by kuberenetes deployments, as container orchestrators have - * not yet been ported over to docker. - */ -@SuppressWarnings({"rawtypes", "ConstantConditions"}) -@EnabledIfEnvironmentVariable(named = "KUBE", - matches = "true") -class ContainerOrchestratorAcceptanceTests { - - private static final Logger LOGGER = LoggerFactory.getLogger(ContainerOrchestratorAcceptanceTests.class); - private static final String AIRBYTE_WORKER = "airbyte-worker"; - private static final String DEFAULT = "default"; - - private static AirbyteAcceptanceTestHarness testHarness; - private static AirbyteApiClient apiClient; - private static UUID workspaceId; - private static KubernetesClient kubernetesClient; - - @SuppressWarnings("UnstableApiUsage") - @BeforeAll - static void init() throws URISyntaxException, IOException, InterruptedException, ApiException { - apiClient = new AirbyteApiClient( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - // work in whatever default workspace is present. - workspaceId = apiClient.getWorkspaceApi().listWorkspaces().getWorkspaces().get(0).getWorkspaceId(); - LOGGER.info("workspaceId = " + workspaceId); - - // log which connectors are being used. - final SourceDefinitionRead sourceDef = apiClient.getSourceDefinitionApi() - .getSourceDefinition(new SourceDefinitionIdRequestBody() - .sourceDefinitionId(UUID.fromString("decd338e-5647-4c0b-adf4-da0e75f5a750"))); - final DestinationDefinitionRead destinationDef = apiClient.getDestinationDefinitionApi() - .getDestinationDefinition(new DestinationDefinitionIdRequestBody() - .destinationDefinitionId(UUID.fromString("25c5221d-dce2-4163-ade9-739ef790f503"))); - LOGGER.info("pg source definition: {}", sourceDef.getDockerImageTag()); - LOGGER.info("pg destination definition: {}", destinationDef.getDockerImageTag()); - - testHarness = new AirbyteAcceptanceTestHarness(apiClient, workspaceId); - kubernetesClient = testHarness.getKubernetesClient(); - } - - @AfterAll - static void end() { - testHarness.stopDbAndContainers(); - } - - @BeforeEach - void setup() throws URISyntaxException, IOException, SQLException { - testHarness.setup(); - } - - // This test is flaky. Warnings are suppressed until that condition us understood - // See: https://github.com/airbytehq/airbyte/issues/19948 - @Test - @Disabled("Flaky test, to be investigated before re-enabling") - @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") - void testDowntimeDuringSync() throws Exception { - // NOTE: PMD assert warning suppressed because the assertion was flaky. The test will throw if the - // sync does not succeed. - final String connectionName = "test-connection"; - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - - LOGGER.info("Creating connection..."); - final UUID connectionId = - testHarness.createConnection(connectionName, sourceId, destinationId, List.of(), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - LOGGER.info("Run manual sync..."); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - LOGGER.info("Waiting for job to run..."); - waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead.getJob(), Set.of(JobStatus.PENDING)); - - LOGGER.info("Scaling down worker..."); - kubernetesClient.apps().deployments().inNamespace(DEFAULT).withName(AIRBYTE_WORKER).scale(0, true); - - LOGGER.info("Scaling up worker..."); - kubernetesClient.apps().deployments().inNamespace(DEFAULT).withName(AIRBYTE_WORKER).scale(1); - - waitForSuccessfulJob(apiClient.getJobsApi(), connectionSyncRead.getJob()); - } - - @AfterEach - void tearDown() { - testHarness.cleanup(); - } - - @Test - void testCancelSyncWithInterruption() throws Exception { - final String connectionName = "test-connection"; - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - final UUID connectionId = - testHarness.createConnection(connectionName, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead.getJob(), Set.of(JobStatus.PENDING)); - - kubernetesClient.apps().deployments().inNamespace(DEFAULT).withName(AIRBYTE_WORKER).scale(0, true); - kubernetesClient.apps().deployments().inNamespace(DEFAULT).withName(AIRBYTE_WORKER).scale(1); - - final var resp = apiClient.getJobsApi().cancelJob(new JobIdRequestBody().id(connectionSyncRead.getJob().getId())); - assertEquals(JobStatus.CANCELLED, resp.getJob().getStatus()); - } - - @Test - void testCancelSyncWhenCancelledWhenWorkerIsNotRunning() throws Exception { - final String connectionName = "test-connection"; - final UUID sourceId = testHarness.createPostgresSource().getSourceId(); - final UUID destinationId = testHarness.createPostgresDestination().getDestinationId(); - final UUID operationId = testHarness.createOperation().getOperationId(); - final AirbyteCatalog catalog = testHarness.discoverSourceSchema(sourceId); - final SyncMode syncMode = SyncMode.FULL_REFRESH; - final DestinationSyncMode destinationSyncMode = DestinationSyncMode.OVERWRITE; - catalog.getStreams().forEach(s -> s.getConfig().syncMode(syncMode).destinationSyncMode(destinationSyncMode)); - - LOGGER.info("Creating connection..."); - final UUID connectionId = - testHarness.createConnection(connectionName, sourceId, destinationId, List.of(operationId), catalog, ConnectionScheduleType.MANUAL, null) - .getConnectionId(); - - LOGGER.info("Waiting for connection to be available in Temporal..."); - - LOGGER.info("Run manual sync..."); - final JobInfoRead connectionSyncRead = apiClient.getConnectionApi().syncConnection(new ConnectionIdRequestBody().connectionId(connectionId)); - - LOGGER.info("Waiting for job to run..."); - waitWhileJobHasStatus(apiClient.getJobsApi(), connectionSyncRead.getJob(), Set.of(JobStatus.PENDING)); - - LOGGER.info("Waiting for job to run a little..."); - Thread.sleep(1000); - - LOGGER.info("Scale down workers..."); - kubernetesClient.apps().deployments().inNamespace(DEFAULT).withName(AIRBYTE_WORKER).scale(0, true); - - LOGGER.info("Starting background cancellation request..."); - final var pool = Executors.newSingleThreadExecutor(); - final var mdc = MDC.getCopyOfContextMap(); - final Future resp = - pool.submit(() -> { - MDC.setContextMap(mdc); - try { - final JobInfoRead jobInfoRead = apiClient.getJobsApi().cancelJob(new JobIdRequestBody().id(connectionSyncRead.getJob().getId())); - LOGGER.info("jobInfoRead = " + jobInfoRead); - return jobInfoRead; - } catch (final ApiException e) { - LOGGER.error("Failed to read from api", e); - throw e; - } - }); - Thread.sleep(2000); - - LOGGER.info("Scaling up workers..."); - kubernetesClient.apps().deployments().inNamespace(DEFAULT).withName(AIRBYTE_WORKER).scale(1); - - LOGGER.info("Waiting for cancellation to go into effect..."); - assertEquals(JobStatus.CANCELLED, resp.get().getJob().getStatus()); - } - -} diff --git a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/VersioningAcceptanceTests.java b/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/VersioningAcceptanceTests.java deleted file mode 100644 index f36977f220142..0000000000000 --- a/airbyte-tests/src/acceptanceTests/java/io/airbyte/test/acceptance/VersioningAcceptanceTests.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.acceptance; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import io.airbyte.api.client.AirbyteApiClient; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.model.generated.CustomDestinationDefinitionCreate; -import io.airbyte.api.client.model.generated.CustomSourceDefinitionCreate; -import io.airbyte.api.client.model.generated.DestinationDefinitionCreate; -import io.airbyte.api.client.model.generated.DestinationDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.DestinationDefinitionRead; -import io.airbyte.api.client.model.generated.SourceDefinitionCreate; -import io.airbyte.api.client.model.generated.SourceDefinitionIdRequestBody; -import io.airbyte.api.client.model.generated.SourceDefinitionRead; -import io.airbyte.test.utils.AirbyteAcceptanceTestHarness; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.util.UUID; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -class VersioningAcceptanceTests { - - private static AirbyteApiClient apiClient; - private static UUID workspaceId; - - private static AirbyteAcceptanceTestHarness testHarness; - - @BeforeAll - static void init() throws ApiException, URISyntaxException, IOException, InterruptedException { - apiClient = new AirbyteApiClient( - new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api")); - - workspaceId = apiClient.getWorkspaceApi().listWorkspaces().getWorkspaces().get(0).getWorkspaceId(); - - testHarness = new AirbyteAcceptanceTestHarness(apiClient, workspaceId); - } - - @AfterAll - static void afterAll() { - testHarness.stopDbAndContainers(); - } - - @BeforeEach - void setup() throws SQLException, URISyntaxException, IOException { - testHarness.setup(); - } - - @AfterEach - void tearDown() { - testHarness.cleanup(); - } - - @ParameterizedTest - @CsvSource({ - "2.1.1, 0.2.0", - "2.1.2, 0.2.1", - }) - void testCreateSourceSpec(final String dockerImageTag, final String expectedProtocolVersion) - throws ApiException, URISyntaxException { - final CustomSourceDefinitionCreate sourceDefinitionCreate = new CustomSourceDefinitionCreate() - .workspaceId(workspaceId) - .sourceDefinition(new SourceDefinitionCreate() - .dockerImageTag(dockerImageTag) - .dockerRepository("airbyte/source-e2e-test") - .documentationUrl(new URI("https://hub.docker.com/r/airbyte/source-e2e-test")) - .name("Source E2E Test Connector")); - - final SourceDefinitionRead sourceDefinitionRead = apiClient.getSourceDefinitionApi().createCustomSourceDefinition(sourceDefinitionCreate); - assertEquals(expectedProtocolVersion, sourceDefinitionRead.getProtocolVersion()); - - final SourceDefinitionIdRequestBody sourceDefinitionReq = new SourceDefinitionIdRequestBody() - .sourceDefinitionId(sourceDefinitionRead.getSourceDefinitionId()); - final SourceDefinitionRead sourceDefinitionReadSanityCheck = - apiClient.getSourceDefinitionApi().getSourceDefinition(sourceDefinitionReq); - assertEquals(sourceDefinitionRead.getProtocolVersion(), sourceDefinitionReadSanityCheck.getProtocolVersion()); - - // Clean up the source - apiClient.getSourceDefinitionApi().deleteSourceDefinition(sourceDefinitionReq); - } - - @ParameterizedTest - @CsvSource({ - "2.1.1, 0.2.0", - "2.1.2, 0.2.1", - }) - void testCreateDestinationSpec(final String dockerImageTag, final String expectedProtocolVersion) - throws ApiException, URISyntaxException { - final CustomDestinationDefinitionCreate destDefinitionCreate = - new CustomDestinationDefinitionCreate() - .workspaceId(workspaceId) - .destinationDefinition(new DestinationDefinitionCreate() - .dockerImageTag(dockerImageTag) - // We are currently using source because the destination-e2e-test connector is facing a regression - // For the purpose of the test, at this moment, using source works because we only check version - .dockerRepository("airbyte/source-e2e-test") - .documentationUrl(new URI("https://hub.docker.com/r/airbyte/destination-e2e-test")) - .name("Dest E2E Test Connector")); - - final DestinationDefinitionRead destDefinitionRead = - apiClient.getDestinationDefinitionApi().createCustomDestinationDefinition(destDefinitionCreate); - assertEquals(expectedProtocolVersion, destDefinitionRead.getProtocolVersion()); - - final DestinationDefinitionIdRequestBody destDefinitionReq = new DestinationDefinitionIdRequestBody() - .destinationDefinitionId(destDefinitionRead.getDestinationDefinitionId()); - final DestinationDefinitionRead destDefinitionReadSanityCheck = - apiClient.getDestinationDefinitionApi().getDestinationDefinition(destDefinitionReq); - assertEquals(destDefinitionRead.getProtocolVersion(), destDefinitionReadSanityCheck.getProtocolVersion()); - - // Clean up the destination - apiClient.getDestinationDefinitionApi().deleteDestinationDefinition(destDefinitionReq); - } - -} diff --git a/airbyte-tests/src/acceptanceTests/resources/postgres_init.sql b/airbyte-tests/src/acceptanceTests/resources/postgres_init.sql deleted file mode 100644 index 0c35dc4576092..0000000000000 --- a/airbyte-tests/src/acceptanceTests/resources/postgres_init.sql +++ /dev/null @@ -1,33 +0,0 @@ -CREATE - TABLE - id_and_name( - id INTEGER NOT NULL, - name VARCHAR(200) - ); - -INSERT - INTO - id_and_name( - id, - name - ) - VALUES( - 1, - 'sherif' - ), - ( - 2, - 'charles' - ), - ( - 3, - 'jared' - ), - ( - 4, - 'michel' - ), - ( - 5, - 'john' - ); diff --git a/airbyte-tests/src/acceptanceTests/resources/postgres_init_cdc.sql b/airbyte-tests/src/acceptanceTests/resources/postgres_init_cdc.sql deleted file mode 100644 index ce7c2da4a5388..0000000000000 --- a/airbyte-tests/src/acceptanceTests/resources/postgres_init_cdc.sql +++ /dev/null @@ -1,79 +0,0 @@ -CREATE - TABLE - id_and_name( - id INTEGER PRIMARY KEY, - name VARCHAR(200) - ); - -INSERT - INTO - id_and_name( - id, - name - ) - VALUES( - 1, - 'sherif' - ), - ( - 2, - 'charles' - ), - ( - 3, - 'jared' - ), - ( - 4, - 'michel' - ), - ( - 5, - 'john' - ); - -CREATE - TABLE - color_palette( - id INTEGER PRIMARY KEY, - color VARCHAR(200) - ); - -INSERT - INTO - color_palette( - id, - color - ) - VALUES( - 1, - 'red' - ), - ( - 2, - 'blue' - ), - ( - 3, - 'green' - ); - -CREATE - ROLE airbyte_role REPLICATION LOGIN; - -ALTER TABLE - id_and_name REPLICA IDENTITY DEFAULT; - -ALTER TABLE - color_palette REPLICA IDENTITY DEFAULT; - -CREATE - PUBLICATION airbyte_publication FOR TABLE - id_and_name, - color_palette; - -SELECT - pg_create_logical_replication_slot( - 'airbyte_slot', - 'pgoutput' - ); diff --git a/airbyte-tests/src/acceptanceTests/resources/postgres_second_schema_multiple_tables.sql b/airbyte-tests/src/acceptanceTests/resources/postgres_second_schema_multiple_tables.sql deleted file mode 100644 index 48414b255763e..0000000000000 --- a/airbyte-tests/src/acceptanceTests/resources/postgres_second_schema_multiple_tables.sql +++ /dev/null @@ -1,58 +0,0 @@ -CREATE - SCHEMA staging; - -CREATE - TABLE - staging.cool_employees( - id INTEGER NOT NULL, - name VARCHAR(200) - ); - -INSERT - INTO - staging.cool_employees( - id, - name - ) - VALUES( - 1, - 'sherif' - ), - ( - 2, - 'charles' - ), - ( - 3, - 'jared' - ), - ( - 4, - 'michel' - ), - ( - 5, - 'john' - ); - -CREATE - TABLE - staging.awesome_people( - id INTEGER NOT NULL, - name VARCHAR(200) - ); - -INSERT - INTO - staging.awesome_people( - id, - name - ) - VALUES( - 1, - 'davin' - ), - ( - 2, - 'chris' - ); diff --git a/airbyte-tests/src/acceptanceTests/resources/postgres_separate_schema_same_table.sql b/airbyte-tests/src/acceptanceTests/resources/postgres_separate_schema_same_table.sql deleted file mode 100644 index 6cf35b644a420..0000000000000 --- a/airbyte-tests/src/acceptanceTests/resources/postgres_separate_schema_same_table.sql +++ /dev/null @@ -1,36 +0,0 @@ -CREATE - SCHEMA staging; - -CREATE - TABLE - staging.id_and_name( - id INTEGER NOT NULL, - name VARCHAR(200) - ); - -INSERT - INTO - staging.id_and_name( - id, - name - ) - VALUES( - 1, - 'sherif' - ), - ( - 2, - 'charles' - ), - ( - 3, - 'jared' - ), - ( - 4, - 'michel' - ), - ( - 5, - 'john' - ); diff --git a/airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/ImportApi.java b/airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/ImportApi.java deleted file mode 100644 index 77ffecfb81d98..0000000000000 --- a/airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/ImportApi.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.automaticMigrationAcceptance; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.invoker.generated.ApiResponse; -import io.airbyte.api.client.model.generated.ImportRead; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.Builder; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.util.function.Consumer; - -/** - * The reason we are using this class instead of - * {@link io.airbyte.api.client.generated.DeploymentApi is cause there is a bug in the the method - * {@link io.airbyte.api.client.generated.DeploymentApi#importArchiveRequestBuilder(File)}, The - * method specifies the content type as `localVarRequestBuilder.header("Content-Type", - * "application/json");` but its supposed to be localVarRequestBuilder.header("Content-Type", - * "application/x-gzip"); - */ -public class ImportApi { - - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; - private final String memberVarBaseUri; - private final Consumer memberVarInterceptor; - private final Duration memberVarReadTimeout; - private final Consumer> memberVarResponseInterceptor; - - public ImportApi(final ApiClient apiClient) { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); - memberVarBaseUri = apiClient.getBaseUri(); - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarReadTimeout = apiClient.getReadTimeout(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - } - - public ImportRead importArchive(final File body) throws ApiException { - final ApiResponse localVarResponse = importArchiveWithHttpInfo(body); - return localVarResponse.getData(); - } - - public ApiResponse importArchiveWithHttpInfo(final File body) throws ApiException { - final HttpRequest.Builder localVarRequestBuilder = importArchiveRequestBuilder(body); - try { - final HttpResponse localVarResponse = memberVarHttpClient.send( - localVarRequestBuilder.build(), - HttpResponse.BodyHandlers.ofInputStream()); - if (memberVarResponseInterceptor != null) { - memberVarResponseInterceptor.accept(localVarResponse); - } - if (errorResponse(localVarResponse)) { - throw new ApiException(localVarResponse.statusCode(), - "importArchive call received non-success response", - localVarResponse.headers(), - localVarResponse.body() == null ? null - : new String(localVarResponse.body().readAllBytes(), StandardCharsets.UTF_8)); - } - return new ApiResponse( - localVarResponse.statusCode(), - localVarResponse.headers().map(), - memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference() {})); - } catch (final IOException e) { - throw new ApiException(e); - } catch (final InterruptedException e) { - Thread.currentThread().interrupt(); - throw new ApiException(e); - } - } - - private Boolean errorResponse(final HttpResponse localVarResponse) { - return localVarResponse.statusCode() / 100 != 2; - } - - private HttpRequest.Builder importArchiveRequestBuilder(final File body) throws ApiException { - // verify the required parameter 'body' is set - if (body == null) { - throw new ApiException(400, - "Missing the required parameter 'body' when calling importArchive"); - } - - final HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); - - final String localVarPath = "/v1/deployment/import"; - - localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); - - localVarRequestBuilder.header("Content-Type", "application/x-gzip"); - localVarRequestBuilder.header("Accept", "application/json"); - - try { - localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofFile(body.toPath())); - } catch (final IOException e) { - throw new ApiException(e); - } - if (memberVarReadTimeout != null) { - localVarRequestBuilder.timeout(memberVarReadTimeout); - } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); - } - return localVarRequestBuilder; - } - -} diff --git a/airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/MigrationAcceptanceTest.java b/airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/MigrationAcceptanceTest.java deleted file mode 100644 index fa5c7276c9ea8..0000000000000 --- a/airbyte-tests/src/automaticMigrationAcceptanceTest/java/io/airbyte/test/automaticMigrationAcceptance/MigrationAcceptanceTest.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2023 Airbyte, Inc., all rights reserved. - */ - -package io.airbyte.test.automaticMigrationAcceptance; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import io.airbyte.api.client.generated.DestinationDefinitionApi; -import io.airbyte.api.client.generated.HealthApi; -import io.airbyte.api.client.generated.SourceDefinitionApi; -import io.airbyte.api.client.generated.WorkspaceApi; -import io.airbyte.api.client.invoker.generated.ApiClient; -import io.airbyte.api.client.invoker.generated.ApiException; -import io.airbyte.api.client.model.generated.DestinationDefinitionRead; -import io.airbyte.api.client.model.generated.SourceDefinitionRead; -import io.airbyte.api.client.model.generated.WorkspaceIdRequestBody; -import io.airbyte.api.client.model.generated.WorkspaceRead; -import io.airbyte.commons.concurrency.VoidCallable; -import io.airbyte.commons.resources.MoreResources; -import io.airbyte.commons.util.MoreProperties; -import io.airbyte.test.container.AirbyteTestContainer; -import java.io.File; -import java.nio.file.Path; -import java.util.List; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; -import java.util.function.Supplier; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class contains an e2e test simulating what a user encounter when trying to upgrade Airybte. - * - upgrading from 0.32.0 to the latest version should work. - This test previously tested - * upgrading from even older versions, which has since been removed - *

- * This test runs on the current code version and expects local images with the `dev` tag to be - * available. To do so, run SUB_BUILD=PLATFORM ./gradlew build. - *

- * When running this test consecutively locally, it might be necessary to run `docker volume prune` - * to remove hanging volumes. - */ -@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert") -class MigrationAcceptanceTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(MigrationAcceptanceTest.class); - - // assume env file is one directory level up from airbyte-tests. - private static final File ENV_FILE = Path.of(System.getProperty("user.dir")).getParent().resolve(".env").toFile(); - - private static final String TEST_DATA_DOCKER_MOUNT = "airbyte_data_migration_test"; - private static final String TEST_DB_DOCKER_MOUNT = "airbyte_db_migration_test"; - private static final String TEST_WORKSPACE_DOCKER_MOUNT = "airbyte_workspace_migration_test"; - private static final String TEST_LOCAL_ROOT = "/tmp/airbyte_local_migration_test"; - private static final String TEST_LOCAL_DOCKER_MOUNT = "/tmp/airbyte_local_migration_test"; - - private static WorkspaceIdRequestBody workspaceIdRequestBody = null; - - @Test - @Disabled - void testAutomaticMigration() throws Exception { - // start at "faux" major version bump version. This was the last version that required db data - // migrations. - final File version32DockerComposeFile = MoreResources.readResourceAsFile("docker-compose-migration-test-0-32-0-alpha.yaml"); - final Properties version32EnvFileProperties = MoreProperties - .envFileToProperties(MoreResources.readResourceAsFile("env-file-migration-test-0-32-0.env")); - runAirbyte(version32DockerComposeFile, version32EnvFileProperties, MigrationAcceptanceTest::assertHealthy); - - final File currentDockerComposeFile = MoreResources.readResourceAsFile("docker-compose.yaml"); - // piggybacks off of whatever the existing .env file is, so override default filesystem values in to - // point at test paths. - final Properties envFileProperties = overrideDirectoriesForTest(MoreProperties.envFileToProperties(ENV_FILE)); - // run from last major version bump to current version. - runAirbyte(currentDockerComposeFile, envFileProperties, MigrationAcceptanceTest::assertHealthy, false); - } - - private Properties overrideDirectoriesForTest(final Properties properties) { - final Properties propertiesWithOverrides = new Properties(properties); - propertiesWithOverrides.put("DATA_DOCKER_MOUNT", TEST_DATA_DOCKER_MOUNT); - propertiesWithOverrides.put("DB_DOCKER_MOUNT", TEST_DB_DOCKER_MOUNT); - propertiesWithOverrides.put("WORKSPACE_DOCKER_MOUNT", TEST_WORKSPACE_DOCKER_MOUNT); - propertiesWithOverrides.put("LOCAL_ROOT", TEST_LOCAL_ROOT); - propertiesWithOverrides.put("LOCAL_DOCKER_MOUNT", TEST_LOCAL_DOCKER_MOUNT); - return propertiesWithOverrides; - } - - private void runAirbyte(final File dockerComposeFile, final Properties env, final VoidCallable assertionExecutable) throws Exception { - runAirbyte(dockerComposeFile, env, assertionExecutable, true); - } - - private void runAirbyte(final File dockerComposeFile, - final Properties env, - final VoidCallable postStartupExecutable, - final boolean retainVolumesOnStop) - throws Exception { - LOGGER.info("Start up Airbyte at version {}", env.get("VERSION")); - final AirbyteTestContainer airbyteTestContainer = new AirbyteTestContainer.Builder(dockerComposeFile) - .setEnv(env) - .build(); - - airbyteTestContainer.startBlocking(); - postStartupExecutable.call(); - if (retainVolumesOnStop) { - airbyteTestContainer.stopRetainVolumes(); - } else { - airbyteTestContainer.stop(); - } - } - - /** - * Allows the test to listen for a specific log line so that the test can end as soon as that log - * line has been encountered. - */ - private static class WaitForLogLine { - - final AtomicBoolean hasSeenLine = new AtomicBoolean(); - - public Consumer getListener(final String stringToListenFor) { - return (logLine) -> { - if (logLine.contains(stringToListenFor)) { - hasSeenLine.set(true); - } - }; - } - - public Supplier hasSeenLine() { - return hasSeenLine::get; - } - - } - - private static void assertHealthy() throws ApiException { - final ApiClient apiClient = getApiClient(); - healthCheck(apiClient); - assertDataFromApi(apiClient); - } - - @SuppressWarnings("PMD.NonThreadSafeSingleton") - private static void assertDataFromApi(final ApiClient apiClient) throws ApiException { - if (workspaceIdRequestBody != null) { - assertEquals(assertWorkspaceInformation(apiClient).getWorkspaceId(), workspaceIdRequestBody.getWorkspaceId()); - } else { - workspaceIdRequestBody = assertWorkspaceInformation(apiClient); - } - - assertSourceDefinitionInformation(apiClient); - assertDestinationDefinitionInformation(apiClient); - } - - private static void assertSourceDefinitionInformation(final ApiClient apiClient) throws ApiException { - final SourceDefinitionApi sourceDefinitionApi = new SourceDefinitionApi(apiClient); - final List sourceDefinitions = sourceDefinitionApi.listSourceDefinitions().getSourceDefinitions(); - assertTrue(sourceDefinitions.size() >= 58); - boolean foundMysqlSourceDefinition = false; - boolean foundPostgresSourceDefinition = false; - for (final SourceDefinitionRead sourceDefinitionRead : sourceDefinitions) { - if ("435bb9a5-7887-4809-aa58-28c27df0d7ad".equals(sourceDefinitionRead.getSourceDefinitionId().toString())) { - assertEquals(sourceDefinitionRead.getName(), "MySQL"); - foundMysqlSourceDefinition = true; - } else if ("decd338e-5647-4c0b-adf4-da0e75f5a750".equals(sourceDefinitionRead.getSourceDefinitionId().toString())) { - assertEquals(sourceDefinitionRead.getName(), "Postgres"); - foundPostgresSourceDefinition = true; - } - } - - assertTrue(foundMysqlSourceDefinition); - assertTrue(foundPostgresSourceDefinition); - } - - private static void assertDestinationDefinitionInformation(final ApiClient apiClient) throws ApiException { - final DestinationDefinitionApi destinationDefinitionApi = new DestinationDefinitionApi(apiClient); - final List destinationDefinitions = destinationDefinitionApi.listDestinationDefinitions().getDestinationDefinitions(); - assertTrue(destinationDefinitions.size() >= 10); - boolean foundPostgresDestinationDefinition = false; - boolean foundLocalCSVDestinationDefinition = false; - boolean foundSnowflakeDestinationDefinition = false; - String destinationId; - for (final DestinationDefinitionRead destinationDefinitionRead : destinationDefinitions) { - destinationId = destinationDefinitionRead.getDestinationDefinitionId().toString(); - if ("25c5221d-dce2-4163-ade9-739ef790f503".equals(destinationId)) { - assertEquals("Postgres", destinationDefinitionRead.getName()); - foundPostgresDestinationDefinition = true; - } else if ("8be1cf83-fde1-477f-a4ad-318d23c9f3c6".equals(destinationId)) { - assertTrue(destinationDefinitionRead.getName().contains("Local CSV")); - foundLocalCSVDestinationDefinition = true; - } else if ("424892c4-daac-4491-b35d-c6688ba547ba".equals(destinationId)) { - assertTrue(destinationDefinitionRead.getName().contains("Snowflake")); - foundSnowflakeDestinationDefinition = true; - } - } - - assertTrue(foundPostgresDestinationDefinition); - assertTrue(foundLocalCSVDestinationDefinition); - assertTrue(foundSnowflakeDestinationDefinition); - } - - private static WorkspaceIdRequestBody assertWorkspaceInformation(final ApiClient apiClient) throws ApiException { - final WorkspaceApi workspaceApi = new WorkspaceApi(apiClient); - final WorkspaceRead workspace = workspaceApi.listWorkspaces().getWorkspaces().get(0); - assertNotNull(workspace.getWorkspaceId().toString()); - assertNotNull(workspace.getName()); - assertNotNull(workspace.getSlug()); - assertEquals(false, workspace.getInitialSetupComplete()); - - return new WorkspaceIdRequestBody().workspaceId(workspace.getWorkspaceId()); - } - - private static void healthCheck(final ApiClient apiClient) { - final HealthApi healthApi = new HealthApi(apiClient); - try { - healthApi.getHealthCheck(); - } catch (final ApiException e) { - throw new RuntimeException("Health check failed, usually due to auto migration failure. Please check the logs for details.", e); - } - } - - private static ApiClient getApiClient() { - return new ApiClient().setScheme("http") - .setHost("localhost") - .setPort(8001) - .setBasePath("/api"); - } - -} diff --git a/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/03a4c904-c91d-447f-ab59-27a43b52c2fd.gz b/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/03a4c904-c91d-447f-ab59-27a43b52c2fd.gz deleted file mode 100644 index 0e9f6b2c40691dcc00e8abc8b4447c2ef71d8ceb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5774 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 M|K}VAcL1&c0L_PN*#H0l diff --git a/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/docker-compose-migration-test-0-32-0-alpha.yaml b/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/docker-compose-migration-test-0-32-0-alpha.yaml deleted file mode 100644 index 10807814277d0..0000000000000 --- a/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/docker-compose-migration-test-0-32-0-alpha.yaml +++ /dev/null @@ -1,203 +0,0 @@ -version: "3.7" -#https://github.com/compose-spec/compose-spec/blob/master/spec.md#using-extensions-as-fragments -x-logging: &default-logging - options: - max-size: "100m" - max-file: "5" - driver: json-file -services: - # hook in case we need to add init behavior - # every root service (no depends_on) should depend on init - init: - image: airbyte/init:${VERSION} - logging: *default-logging - container_name: init - command: /bin/sh -c "./scripts/create_mount_directories.sh /local_parent ${HACK_LOCAL_ROOT_PARENT} ${LOCAL_ROOT}" - environment: - - LOCAL_ROOT=${LOCAL_ROOT} - - HACK_LOCAL_ROOT_PARENT=${HACK_LOCAL_ROOT_PARENT} - volumes: - - ${HACK_LOCAL_ROOT_PARENT}:/local_parent - db: - image: airbyte/db:${VERSION} - logging: *default-logging - container_name: airbyte-db - restart: unless-stopped - environment: - - POSTGRES_USER=${DATABASE_USER} - - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - - DATABASE_USER=${DATABASE_USER} - - DATABASE_PASSWORD=${DATABASE_PASSWORD} - - DATABASE_URL=${DATABASE_URL} - - CONFIG_DATABASE_USER=${CONFIG_DATABASE_USER:-} - - CONFIG_DATABASE_PASSWORD=${CONFIG_DATABASE_PASSWORD:-} - - CONFIG_DATABASE_URL=${CONFIG_DATABASE_URL:-} - volumes: - - db:/var/lib/postgresql/data - scheduler: - image: airbyte/scheduler:${VERSION} - logging: *default-logging - container_name: airbyte-scheduler - restart: unless-stopped - environment: - - WEBAPP_URL=${WEBAPP_URL} - - DATABASE_USER=${DATABASE_USER} - - DATABASE_PASSWORD=${DATABASE_PASSWORD} - - DATABASE_URL=${DATABASE_URL} - - CONFIG_DATABASE_USER=${CONFIG_DATABASE_USER:-} - - CONFIG_DATABASE_PASSWORD=${CONFIG_DATABASE_PASSWORD:-} - - CONFIG_DATABASE_URL=${CONFIG_DATABASE_URL:-} - - RUN_DATABASE_MIGRATION_ON_STARTUP=${RUN_DATABASE_MIGRATION_ON_STARTUP} - - WORKSPACE_ROOT=${WORKSPACE_ROOT} - - WORKSPACE_DOCKER_MOUNT=${WORKSPACE_DOCKER_MOUNT} - - LOCAL_ROOT=${LOCAL_ROOT} - - LOCAL_DOCKER_MOUNT=${LOCAL_DOCKER_MOUNT} - - CONFIG_ROOT=${CONFIG_ROOT} - - TRACKING_STRATEGY=${TRACKING_STRATEGY} - - AIRBYTE_VERSION=${VERSION} - - AIRBYTE_ROLE=${AIRBYTE_ROLE:-} - - TEMPORAL_HOST=${TEMPORAL_HOST} - - WORKER_ENVIRONMENT=${WORKER_ENVIRONMENT} - - S3_LOG_BUCKET=${S3_LOG_BUCKET} - - S3_LOG_BUCKET_REGION=${S3_LOG_BUCKET_REGION} - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - - GCP_STORAGE_BUCKET=${GCP_STORAGE_BUCKET} - - LOG_LEVEL=${LOG_LEVEL} - - SUBMITTER_NUM_THREADS=${SUBMITTER_NUM_THREADS} - - RESOURCE_CPU_REQUEST=${RESOURCE_CPU_REQUEST} - - RESOURCE_CPU_LIMIT=${RESOURCE_CPU_LIMIT} - - RESOURCE_MEMORY_REQUEST=${RESOURCE_MEMORY_REQUEST} - - RESOURCE_MEMORY_LIMIT=${RESOURCE_MEMORY_LIMIT} - - MAX_SYNC_JOB_ATTEMPTS=${MAX_SYNC_JOB_ATTEMPTS} - - MAX_SYNC_TIMEOUT_DAYS=${MAX_SYNC_TIMEOUT_DAYS} - - INTERNAL_API_HOST=${INTERNAL_API_HOST} - - SECRET_PERSISTENCE=${SECRET_PERSISTENCE} - volumes: - - workspace:${WORKSPACE_ROOT} - - ${LOCAL_ROOT}:${LOCAL_ROOT} - - data:${CONFIG_ROOT} - worker: - image: airbyte/worker:${VERSION} - logging: *default-logging - container_name: airbyte-worker - restart: unless-stopped - environment: - - WEBAPP_URL=${WEBAPP_URL} - - DATABASE_USER=${DATABASE_USER} - - DATABASE_PASSWORD=${DATABASE_PASSWORD} - - DATABASE_URL=${DATABASE_URL} - - CONFIG_DATABASE_USER=${CONFIG_DATABASE_USER:-} - - CONFIG_DATABASE_PASSWORD=${CONFIG_DATABASE_PASSWORD:-} - - CONFIG_DATABASE_URL=${CONFIG_DATABASE_URL:-} - - RUN_DATABASE_MIGRATION_ON_STARTUP=${RUN_DATABASE_MIGRATION_ON_STARTUP} - - WORKSPACE_ROOT=${WORKSPACE_ROOT} - - WORKSPACE_DOCKER_MOUNT=${WORKSPACE_DOCKER_MOUNT} - - LOCAL_ROOT=${LOCAL_ROOT} - - LOCAL_DOCKER_MOUNT=${LOCAL_DOCKER_MOUNT} - - CONFIG_ROOT=${CONFIG_ROOT} - - TRACKING_STRATEGY=${TRACKING_STRATEGY} - - AIRBYTE_VERSION=${VERSION} - - AIRBYTE_ROLE=${AIRBYTE_ROLE:-} - - TEMPORAL_HOST=${TEMPORAL_HOST} - - WORKER_ENVIRONMENT=${WORKER_ENVIRONMENT} - - S3_LOG_BUCKET=${S3_LOG_BUCKET} - - S3_LOG_BUCKET_REGION=${S3_LOG_BUCKET_REGION} - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - - GCP_STORAGE_BUCKET=${GCP_STORAGE_BUCKET} - - LOG_LEVEL=${LOG_LEVEL} - - SUBMITTER_NUM_THREADS=${SUBMITTER_NUM_THREADS} - - RESOURCE_CPU_REQUEST=${RESOURCE_CPU_REQUEST} - - RESOURCE_CPU_LIMIT=${RESOURCE_CPU_LIMIT} - - RESOURCE_MEMORY_REQUEST=${RESOURCE_MEMORY_REQUEST} - - RESOURCE_MEMORY_LIMIT=${RESOURCE_MEMORY_LIMIT} - - MAX_SYNC_JOB_ATTEMPTS=${MAX_SYNC_JOB_ATTEMPTS} - - MAX_SYNC_TIMEOUT_DAYS=${MAX_SYNC_TIMEOUT_DAYS} - - INTERNAL_API_HOST=${INTERNAL_API_HOST} - - SECRET_PERSISTENCE=${SECRET_PERSISTENCE} - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - workspace:${WORKSPACE_ROOT} - - ${LOCAL_ROOT}:${LOCAL_ROOT} - server: - image: airbyte/server:${VERSION} - logging: *default-logging - container_name: airbyte-server - restart: unless-stopped - environment: - - WEBAPP_URL=${WEBAPP_URL} - - DATABASE_USER=${DATABASE_USER} - - DATABASE_PASSWORD=${DATABASE_PASSWORD} - - DATABASE_URL=${DATABASE_URL} - - CONFIG_DATABASE_USER=${CONFIG_DATABASE_USER:-} - - CONFIG_DATABASE_PASSWORD=${CONFIG_DATABASE_PASSWORD:-} - - CONFIG_DATABASE_URL=${CONFIG_DATABASE_URL:-} - - RUN_DATABASE_MIGRATION_ON_STARTUP=${RUN_DATABASE_MIGRATION_ON_STARTUP} - - WORKSPACE_ROOT=${WORKSPACE_ROOT} - - CONFIG_ROOT=${CONFIG_ROOT} - - TRACKING_STRATEGY=${TRACKING_STRATEGY} - - AIRBYTE_VERSION=${VERSION} - - AIRBYTE_ROLE=${AIRBYTE_ROLE:-} - - TEMPORAL_HOST=${TEMPORAL_HOST} - - WORKER_ENVIRONMENT=${WORKER_ENVIRONMENT} - - S3_LOG_BUCKET=${S3_LOG_BUCKET} - - S3_LOG_BUCKET_REGION=${S3_LOG_BUCKET_REGION} - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - - GCP_STORAGE_BUCKET=${GCP_STORAGE_BUCKET} - - LOG_LEVEL=${LOG_LEVEL} - - RESOURCE_CPU_REQUEST=${RESOURCE_CPU_REQUEST} - - RESOURCE_CPU_LIMIT=${RESOURCE_CPU_LIMIT} - - RESOURCE_MEMORY_REQUEST=${RESOURCE_MEMORY_REQUEST} - - RESOURCE_MEMORY_LIMIT=${RESOURCE_MEMORY_LIMIT} - - SECRET_PERSISTENCE=${SECRET_PERSISTENCE} - - VERSION_0_32_0_FORCE_UPGRADE=${VERSION_0_32_0_FORCE_UPGRADE} - ports: - - 8001:8001 - volumes: - - workspace:${WORKSPACE_ROOT} - - data:${CONFIG_ROOT} - - ${LOCAL_ROOT}:${LOCAL_ROOT} - webapp: - image: airbyte/webapp:${VERSION} - logging: *default-logging - container_name: airbyte-webapp - restart: unless-stopped - ports: - - 8000:80 - environment: - - AIRBYTE_ROLE=${AIRBYTE_ROLE:-} - - AIRBYTE_VERSION=${VERSION} - - API_URL=${API_URL:-} - - TRACKING_STRATEGY=${TRACKING_STRATEGY} - - INTERNAL_API_HOST=${INTERNAL_API_HOST} - - OPENREPLAY=${OPENREPLAY:-} - - PAPERCUPS_STORYTIME=${PAPERCUPS_STORYTIME:-} - airbyte-temporal: - image: airbyte/temporal:${VERSION} - logging: *default-logging - container_name: airbyte-temporal - restart: unless-stopped - ports: - - 7233:7233 - environment: - - DB=postgresql - - DB_PORT=${DATABASE_PORT} - - POSTGRES_USER=${DATABASE_USER} - - POSTGRES_PWD=${DATABASE_PASSWORD} - - POSTGRES_SEEDS=${DATABASE_HOST} - - DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml - - LOG_LEVEL=${LOG_LEVEL} - volumes: - - ./temporal/dynamicconfig:/etc/temporal/config/dynamicconfig -volumes: - workspace: - name: ${WORKSPACE_DOCKER_MOUNT} - # the data volume is only needed for backward compatibility; when users upgrade - # from an old Airbyte version that relies on file-based configs, the server needs - # to read this volume to copy their configs to the database - data: - name: ${DATA_DOCKER_MOUNT} - db: - name: ${DB_DOCKER_MOUNT} diff --git a/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/env-file-migration-test-0-32-0.env b/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/env-file-migration-test-0-32-0.env deleted file mode 100644 index 2dd0169e21463..0000000000000 --- a/airbyte-tests/src/automaticMigrationAcceptanceTest/resources/env-file-migration-test-0-32-0.env +++ /dev/null @@ -1,86 +0,0 @@ -VERSION=0.32.0-alpha-patch-1 - -# Airbyte Internal Job Database, see https://docs.airbyte.io/operator-guides/configuring-airbyte-db -DATABASE_USER=docker -DATABASE_PASSWORD=docker -DATABASE_HOST=db -DATABASE_PORT=5432 -DATABASE_DB=airbyte -# translate manually DATABASE_URL=jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT/${DATABASE_DB} (do not include the username or password here) -DATABASE_URL=jdbc:postgresql://db:5432/airbyte - -# Airbyte Internal Config Database, default to reuse the Job Database when they are empty -# Usually you do not need to set them; they are explicitly left empty to mute docker compose warnings -CONFIG_DATABASE_USER= -CONFIG_DATABASE_PASSWORD= -CONFIG_DATABASE_URL= - -RUN_DATABASE_MIGRATION_ON_STARTUP=true - -# When using the airbyte-db via default docker image: -CONFIG_ROOT=/data -DATA_DOCKER_MOUNT=airbyte_data_migration_test -DB_DOCKER_MOUNT=airbyte_db_migration_test - -# Temporal.io worker configuration -TEMPORAL_HOST=airbyte-temporal:7233 - -# Workspace storage for running jobs (logs, etc) -WORKSPACE_ROOT=/tmp/workspace -WORKSPACE_DOCKER_MOUNT=airbyte_workspace_migration_test - -# Local mount to access local files from filesystem -# todo (cgardens) - when we are mount raw directories instead of named volumes, *_DOCKER_MOUNT must -# be the same as *_ROOT. -# Issue: https://github.com/airbytehq/airbyte/issues/578 -LOCAL_ROOT=/tmp/airbyte_local_migration_test -LOCAL_DOCKER_MOUNT=/tmp/airbyte_local_migration_test -# todo (cgardens) - hack to handle behavior change in docker compose. *_PARENT directories MUST -# already exist on the host filesystem and MUST be parents of *_ROOT. -# Issue: https://github.com/airbytehq/airbyte/issues/577 -HACK_LOCAL_ROOT_PARENT=/tmp - -# Maximum simultaneous jobs -SUBMITTER_NUM_THREADS=10 - -# Job container images -# Usually you should not need to set these, they have defaults already set -JOB_KUBE_SOCAT_IMAGE= -JOB_KUBE_BUSYBOX_IMAGE= -JOB_KUBE_CURL_IMAGE= - -# Miscellaneous -TRACKING_STRATEGY=segment -WEBAPP_URL=http://localhost:8000/ -API_URL=/api/v1/ -INTERNAL_API_HOST=airbyte-server:8001 -LOG_LEVEL=INFO - -WORKER_ENVIRONMENT=docker - -# Cloud log backups. Don't use this unless you know what you're doing. Mainly for Airbyte devs. -# If you just want to capture Docker logs, you probably want to use something like this instead: -# https://docs.docker.com/config/containers/logging/configure/ -S3_LOG_BUCKET= -S3_LOG_BUCKET_REGION= -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -S3_MINIO_ENDPOINT= -S3_PATH_STYLE_ACCESS= - -GCP_STORAGE_BUCKET= - -# Docker Resource Limits -RESOURCE_CPU_REQUEST= -RESOURCE_CPU_LIMIT= -RESOURCE_MEMORY_REQUEST= -RESOURCE_MEMORY_LIMIT= - -# Max attempts per sync and max retries per attempt -MAX_SYNC_JOB_ATTEMPTS=3 - -# Time in days to reach a timeout to cancel the synchronization -MAX_SYNC_TIMEOUT_DAYS=3 - -# Set secret persistence store to use. Do not change this for existing installations! -SECRET_PERSISTENCE=NONE diff --git a/airbyte-webapp-e2e-tests/.eslintrc.js b/airbyte-webapp-e2e-tests/.eslintrc.js deleted file mode 100644 index f0abf5c00175f..0000000000000 --- a/airbyte-webapp-e2e-tests/.eslintrc.js +++ /dev/null @@ -1,52 +0,0 @@ -module.exports = { - env: { - browser: true, - node: true, - }, - extends: [ - "plugin:cypress/recommended", - "plugin:@typescript-eslint/recommended", - "prettier", - "plugin:prettier/recommended", - ], - plugins: ["@typescript-eslint", "prettier"], - parser: "@typescript-eslint/parser", - rules: { - "cypress/no-unnecessary-waiting": "warn", - "prettier/prettier": "warn", - - curly: "warn", - "dot-location": ["warn", "property"], - "dot-notation": "warn", - "no-else-return": "warn", - "no-lonely-if": "warn", - "no-inner-declarations": "off", - "no-unused-vars": "off", - "no-useless-computed-key": "warn", - "no-useless-return": "warn", - "no-var": "warn", - "object-shorthand": ["warn", "always"], - "prefer-arrow-callback": "warn", - "prefer-const": "warn", - "prefer-destructuring": ["warn", { AssignmentExpression: { array: true } }], - "prefer-object-spread": "warn", - "prefer-template": "warn", - "spaced-comment": ["warn", "always", { markers: ["/"] }], - yoda: "warn", - - "@typescript-eslint/array-type": ["warn", { default: "array-simple" }], - "@typescript-eslint/ban-ts-comment": [ - "warn", - { - "ts-expect-error": "allow-with-description", - }, - ], - "@typescript-eslint/ban-types": "warn", - "@typescript-eslint/consistent-indexed-object-style": ["warn", "record"], - "@typescript-eslint/consistent-type-definitions": ["warn", "interface"], - "@typescript-eslint/no-unused-vars": "warn", - - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/triple-slash-reference": "off", - }, -}; diff --git a/airbyte-webapp-e2e-tests/.gitignore b/airbyte-webapp-e2e-tests/.gitignore deleted file mode 100644 index 15386a1f0f808..0000000000000 --- a/airbyte-webapp-e2e-tests/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -*.iml -/.idea - -.env -.env.development -.env.production - -/cypress/screenshots -/cypress/videos -/cypress/fixtures -/cypress/downloads diff --git a/airbyte-webapp-e2e-tests/.npmrc b/airbyte-webapp-e2e-tests/.npmrc deleted file mode 100644 index b6f27f1359546..0000000000000 --- a/airbyte-webapp-e2e-tests/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true diff --git a/airbyte-webapp-e2e-tests/.nvmrc b/airbyte-webapp-e2e-tests/.nvmrc deleted file mode 100644 index a2d511aff36c3..0000000000000 --- a/airbyte-webapp-e2e-tests/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -16.18.1 \ No newline at end of file diff --git a/airbyte-webapp-e2e-tests/.prettierrc.js b/airbyte-webapp-e2e-tests/.prettierrc.js deleted file mode 120000 index d0e72529dfa17..0000000000000 --- a/airbyte-webapp-e2e-tests/.prettierrc.js +++ /dev/null @@ -1 +0,0 @@ -../airbyte-webapp/.prettierrc.js \ No newline at end of file diff --git a/airbyte-webapp-e2e-tests/README.md b/airbyte-webapp-e2e-tests/README.md deleted file mode 100644 index 4774d55b19cea..0000000000000 --- a/airbyte-webapp-e2e-tests/README.md +++ /dev/null @@ -1,38 +0,0 @@ -## Running an interactive Cypress session with `npm run cypress:open` -The most useful way to run tests locally is with the `cypress open` command. It opens a dispatcher window that lets you select which tests and browser to run; the Electron browser (whose devtools will be very familiar to chrome users) opens a child window, and having both cypress windows grouped behaves nicely when switching between applications. In an interactive session, you can use `it.skip` and `it.only` to focus on the tests you care about; any change to the source file of a running test will cause tests to be automatically rerun. At the end of a test run, the web page is left "dangling" with all state present at the end of the last test; you can click around, "inspect element", and interact with the page however you wish, which makes it easy to incrementally develop tests. - -By default, this command is configured to visit page urls from port 3000 (as used by a locally-run dev server), not port 8000 (as used by docker-compose's `webapp` service). If you want to run tests against the dockerized UI instead, leave the `webapp` docker-compose service running in step 4) and start the test runner with `CYPRESS_BASE_URL=http://localhost:8000 npm run cypress:open` in step 8). - -Except as noted, all commands are written as if run from inside the `airbyte-webapp-e2e-tests/` directory. - -Steps: -1) If you have not already done so, run `npm install` to install the e2e test dependencies. -2) Build the OSS backend for the current commit with `SUB_BUILD=PLATFORM ../gradlew clean build`. -3) Create the test database: `npm run createdbsource` and `npm run createdbdestination`. -4) When running the connector builder tests, start the dummy API server: `npm run createdummyapi` -5) Start the OSS backend: `BASIC_AUTH_USERNAME="" BASIC_AUTH_PASSWORD="" VERSION=dev docker compose --file ../docker-compose.yaml up`. If you want, follow this with `docker compose stop webapp` to turn off the dockerized frontend build; interactive cypress sessions don't use it. -6) The following two commands will start a separate long-running server, so open another terminal window. In it, `cd` into the `airbyte-webapp/` directory. -7) If you have not already done so, run `pnpm install` to install the frontend app's dependencies. -8) Start the frontend development server with `pnpm start`. -9) Back in the `airbyte-webapp-e2e-tests/` directory, start the cypress test runner with `npm run cypress:open`. - -## Reproducing CI test results with `npm run cypress:ci` or `npm run cypress:ci:record` -Unlike `npm run cypress:open`, `npm run cypress:ci` and `npm run cypress:ci:record` use the dockerized UI (i.e. they expect the UI at port 8000, rather than port 3000). If the OSS backend is running but you have run `docker-compose stop webapp`, you'll have to re-enable it with `docker-compose start webapp`. These trigger headless runs: you won't have a live browser to interact with, just terminal output. - -Except as noted, all commands are written as if run from inside the `airbyte-webapp-e2e-tests/` directory. - -Steps: -1) If you have not already done so, run `npm install` to install the e2e test dependencies. -2) Build the OSS backend for the current commit with `SUB_BUILD=PLATFORM ../gradlew clean build`. -3) Create the test database: `npm run createdbsource` and `npm run createdbdestination`. -4) When running the connector builder tests, start the dummy API server: `npm run createdummyapi` -5) Start the OSS backend: `BASIC_AUTH_USERNAME="" BASIC_AUTH_PASSWORD="" VERSION=dev docker compose --file ../docker-compose.yaml up`. -6) Start the cypress test run with `npm run cypress:ci` or `npm run cypress:ci:record`. - -## Test setup - -When the tests are run as described above, the platform under test is started via docker compose on the local docker host. To test connections from real sources and destinations, additional docker containers are started for hosting these. For basic connections, additional postgres instances are started (`createdbsource` and `createdbdestination`). - -For testing the connector builder UI, a dummy api server based on a node script is started (`createdummyapi`). It is providing a simple http API with bearer authentication returning a few records of hardcoded data. By running it in the internal airbyte network, the connector builder server can access it under its container name. - -The tests in here are instrumenting a Chrome instance to test the full functionality of Airbyte from the frontend, so other components of the platform (scheduler, worker, connector builder server) are also tested in a rudimentary way. diff --git a/airbyte-webapp-e2e-tests/build.gradle b/airbyte-webapp-e2e-tests/build.gradle deleted file mode 100644 index 9a2389aac681d..0000000000000 --- a/airbyte-webapp-e2e-tests/build.gradle +++ /dev/null @@ -1,28 +0,0 @@ -plugins { - id "base" - id "com.github.node-gradle.node" version "3.3.0" -} - -def nodeVersion = new File("${projectDir}/.nvmrc").text.trim(); - -node { - download = true - version = nodeVersion -} - -task e2etest(type: NpmTask) { - dependsOn npmInstall - // If the cypressWebappKey property has been set from the outside (see tools/bin/e2e_test.sh) - // we'll record the cypress session, otherwise we're not recording - def recordCypress = project.hasProperty('cypressWebappKey') && project.getProperty('cypressWebappKey') - if (recordCypress) { - environment = [CYPRESS_KEY: project.getProperty('cypressWebappKey')] - args = ['run', 'cypress:ci:record'] - } else { - args = ['run', 'cypress:ci'] - } - inputs.files fileTree('cypress') - inputs.file 'package.json' - inputs.file 'package-lock.json' -} - diff --git a/airbyte-webapp-e2e-tests/cypress.json b/airbyte-webapp-e2e-tests/cypress.json deleted file mode 100644 index 995bc36be2dee..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "projectId": "916nvw", - "baseUrl": "https://localhost:3000", - "testFiles": ["**/*.spec.*"], - "viewportHeight": 800, - "viewportWidth": 1280, - "retries": { - "runMode": 5, - "openMode": 0 - }, - "defaultCommandTimeout": 10000, - "db": { - "user": "postgres", - "host": "localhost", - "database": "airbyte_ci_source", - "password": "secret_password", - "port": 5433 - } -} diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts deleted file mode 100644 index a7e4ea35d2182..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - ConnectionGetBody, - Connection, - ConnectionCreateRequestBody, - ConnectionsList, - Destination, - DestinationsList, - Source, - SourceDiscoverSchema, - SourcesList, -} from "./types"; -import { getWorkspaceId, setWorkspaceId } from "./workspace"; - -const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; - -const apiRequest = ( - method: Cypress.HttpMethod, - path: string, - payload?: Cypress.RequestBody, - expectedStatus = 200 -): Cypress.Chainable => - cy.request(method, getApiUrl(path), payload).then((response) => { - expect(response.status).to.eq(expectedStatus, "response status"); - return response.body; - }); - -export const requestWorkspaceId = () => - apiRequest<{ workspaces: Array<{ workspaceId: string }> }>("POST", "/workspaces/list").then( - ({ workspaces: [{ workspaceId }] }) => { - setWorkspaceId(workspaceId); - } - ); - -export const requestConnectionsList = () => - apiRequest("POST", "/connections/list", { workspaceId: getWorkspaceId() }); - -export const requestCreateConnection = (body: ConnectionCreateRequestBody) => - apiRequest("POST", "/web_backend/connections/create", body); - -export const requestUpdateConnection = (body: Record) => - apiRequest("POST", "/web_backend/connections/update", body); - -export const requestGetConnection = (body: ConnectionGetBody) => - apiRequest("POST", "/web_backend/connections/get", body); - -export const requestDeleteConnection = (connectionId: string) => - apiRequest("POST", "/connections/delete", { connectionId }, 204); - -export const requestSourcesList = () => - apiRequest("POST", "/sources/list", { workspaceId: getWorkspaceId() }); - -export const requestSourceDiscoverSchema = (sourceId: string) => - apiRequest("POST", "/sources/discover_schema", { sourceId, disable_cache: true }); - -export const requestCreateSource = (body: Record) => - apiRequest("POST", "/sources/create", body); - -export const requestDeleteSource = (sourceId: string) => apiRequest("POST", "/sources/delete", { sourceId }, 204); - -export const requestDestinationsList = () => - apiRequest("POST", "/destinations/list", { workspaceId: getWorkspaceId() }); - -export const requestCreateDestination = (body: Record) => - apiRequest("POST", "/destinations/create", body); - -export const requestDeleteDestination = (destinationId: string) => - apiRequest("POST", "/destinations/delete", { destinationId }, 204); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/index.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/index.ts deleted file mode 100644 index f5d0fb3b55c29..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./api"; -export * from "./payloads"; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts deleted file mode 100644 index 44db5c99d5015..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { ConnectionCreateRequestBody } from "./types"; -import { getWorkspaceId } from "./workspace"; - -type RequiredConnectionCreateRequestProps = "name" | "sourceId" | "destinationId" | "syncCatalog" | "sourceCatalogId"; -type CreationConnectRequestParams = Pick & - Partial>; - -export const getConnectionCreateRequest = (params: CreationConnectRequestParams): ConnectionCreateRequestBody => ({ - geography: "auto", - namespaceDefinition: "source", - namespaceFormat: "${SOURCE_NAMESPACE}", - nonBreakingChangesPreference: "ignore", - operations: [], - prefix: "", - scheduleType: "manual", - status: "active", - ...params, -}); - -export const getPostgresCreateSourceBody = (name: string) => ({ - name, - sourceDefinitionId: "decd338e-5647-4c0b-adf4-da0e75f5a750", - workspaceId: getWorkspaceId(), - connectionConfiguration: { - ssl_mode: { mode: "disable" }, - tunnel_method: { tunnel_method: "NO_TUNNEL" }, - replication_method: { method: "Standard" }, - ssl: false, - port: 5433, - schemas: ["public"], - host: "localhost", - database: "airbyte_ci_source", - username: "postgres", - password: "secret_password", - }, -}); - -export const getE2ETestingCreateDestinationBody = (name: string) => ({ - name, - workspaceId: getWorkspaceId(), - destinationDefinitionId: "2eb65e87-983a-4fd7-b3e3-9d9dc6eb8537", - connectionConfiguration: { - type: "LOGGING", - logging_config: { - logging_type: "FirstN", - max_entry_count: 100, - }, - }, -}); - -export const getPostgresCreateDestinationBody = (name: string) => ({ - name, - workspaceId: getWorkspaceId(), - destinationDefinitionId: "25c5221d-dce2-4163-ade9-739ef790f503", - connectionConfiguration: { - ssl_mode: { mode: "disable" }, - tunnel_method: { tunnel_method: "NO_TUNNEL" }, - ssl: false, - port: 5434, - schema: "public", - host: "localhost", - database: "airbyte_ci_destination", - username: "postgres", - password: "secret_password", - }, -}); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts deleted file mode 100644 index f21ebd75b1120..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts +++ /dev/null @@ -1,77 +0,0 @@ -export interface Connection { - connectionId: string; - destination: Destination; - destinationId: string; - isSyncing: boolean; - name: string; - scheduleType: string; - schemaChange: string; - source: Source; - sourceId: string; - status: "active" | "inactive" | "deprecated"; - nonBreakingChangesPreference: "ignore" | "disable"; - syncCatalog: SyncCatalog; -} - -export interface ConnectionCreateRequestBody { - destinationId: string; - geography: string; - name: string; - namespaceDefinition: string; - namespaceFormat: string; - nonBreakingChangesPreference: "ignore" | "disable"; - operations: unknown[]; - prefix: string; - scheduleType: string; - sourceCatalogId: string; - sourceId: string; - status: "active"; - syncCatalog: SyncCatalog; -} - -export interface ConnectionGetBody { - connectionId: string; - withRefreshedCatalog?: boolean; -} - -export interface ConnectionsList { - connections: Connection[]; -} - -export interface Destination { - name: string; - destinationDefinitionId: string; - destinationName: string; - destinationId: string; - connectionConfiguration: Record; -} - -export interface DestinationsList { - destinations: Destination[]; -} - -export interface Source { - name: string; - sourceDefinitionId: string; - sourceName: string; - sourceId: string; - connectionConfiguration: Record; -} - -export interface SourceDiscoverSchema { - catalog: SyncCatalog; - catalogId: string; -} - -export interface SourcesList { - sources: Source[]; -} - -export interface SyncCatalog { - streams: SyncCatalogStream[]; -} - -export interface SyncCatalogStream { - config: Record; - stream: Record; -} diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts deleted file mode 100644 index 9e1bcf6c1d254..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts +++ /dev/null @@ -1,9 +0,0 @@ -let _workspaceId: string; - -export const setWorkspaceId = (workspaceId: string) => { - _workspaceId = workspaceId; -}; - -export const getWorkspaceId = () => { - return _workspaceId; -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/common.ts b/airbyte-webapp-e2e-tests/cypress/commands/common.ts deleted file mode 100644 index 39ad108232fd7..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/common.ts +++ /dev/null @@ -1,51 +0,0 @@ -export const submitButtonClick = (force: boolean = false) => { - cy.get("button[type=submit]").click({ force: force }); -}; - -export const updateField = (field: string, value: string) => { - cy.get(`input[name='${field}']`).clear().type(value); -}; - -export const openSettingForm = (name: string) => { - cy.get("div").contains(name).click(); - cy.get("div[data-id='settings-step']").click(); -}; - -export const deleteEntity = () => { - cy.get("button[data-id='open-delete-modal']").click(); - cy.get("button[data-id='delete']").click(); -}; - -export const clearApp = () => { - indexedDB.deleteDatabase("firebaseLocalStorageDb"); - cy.clearLocalStorage(); - cy.clearCookies(); -}; - -export const fillEmail = (email: string) => { - cy.get("input[name=email]").type(email); -}; - -// useful for ensuring that a name is unique from one test run to the next -export const appendRandomString = (string: string) => { - const randomString = Math.random().toString(36).substring(2, 10); - return `${string} _${randomString}`; -}; - -/** - * Click on specific cell found by column name in desired table - * @param tableSelector - table selector - * @param columnName - column name - * @param connectName - cell text - */ -export const clickOnCellInTable = (tableSelector: string, columnName: string, connectName: string) => { - cy.contains(`${tableSelector} th`, columnName) - .invoke("index") - .then((value) => { - cy.log(`${value}`); - return cy.wrap(value); - }) - .then((columnIndex) => { - cy.contains("tbody tr", connectName).find("td").eq(columnIndex).click(); - }); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/connection.ts b/airbyte-webapp-e2e-tests/cypress/commands/connection.ts deleted file mode 100644 index 07d7e351a64c3..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/connection.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { submitButtonClick } from "./common"; -import { createLocalJsonDestination, createPostgresDestination } from "./destination"; -import { createPokeApiSource, createPostgresSource } from "./source"; -import { openAddSource } from "pages/destinationPage"; -import { selectSchedule, setupDestinationNamespaceSourceFormat, enterConnectionName } from "pages/replicationPage"; - -export const createTestConnection = (sourceName: string, destinationName: string) => { - cy.intercept("/api/v1/sources/discover_schema").as("discoverSchema"); - cy.intercept("/api/v1/web_backend/connections/create").as("createConnection"); - - switch (true) { - case sourceName.includes("PokeAPI"): - createPokeApiSource(sourceName, "luxray"); - break; - - case sourceName.includes("Postgres"): - createPostgresSource(sourceName); - break; - default: - createPostgresSource(sourceName); - } - - switch (true) { - case destinationName.includes("Postgres"): - createPostgresDestination(destinationName); - break; - case destinationName.includes("JSON"): - createLocalJsonDestination(destinationName); - break; - default: - createLocalJsonDestination(destinationName); - } - - cy.wait(5000); - - openAddSource(); - cy.get("div").contains(sourceName).click(); - - cy.wait("@discoverSchema"); - - enterConnectionName("Connection name"); - selectSchedule("Manual"); - - setupDestinationNamespaceSourceFormat(); - submitButtonClick(); - - cy.wait("@createConnection", { requestTimeout: 10000 }); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/connector.ts b/airbyte-webapp-e2e-tests/cypress/commands/connector.ts deleted file mode 100644 index 9e3ab477c1c36..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/connector.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { - enterDestinationPath, - selectServiceType, - enterName, - enterHost, - enterPort, - enterDatabase, - enterUsername, - enterPassword, - enterPokemonName, - enterSchema, -} from "pages/createConnectorPage"; - -export const fillPostgresForm = ( - name: string, - host: string, - port: string, - database: string, - username: string, - password: string, - schema: string -) => { - cy.intercept("/api/v1/source_definition_specifications/get").as("getSourceSpecifications"); - - selectServiceType("Postgres"); - - enterName(name); - enterHost(host); - enterPort(port); - enterDatabase(database); - enterSchema(schema); - enterUsername(username); - enterPassword(password); -}; - -export const fillPokeAPIForm = (name: string, pokeName: string) => { - cy.intercept("/api/v1/source_definition_specifications/get").as("getSourceSpecifications"); - - selectServiceType("PokeAPI"); - - enterName(name); - enterPokemonName(pokeName); -}; - -export const fillLocalJsonForm = (name: string, destinationPath: string) => { - cy.intercept("/api/v1/destination_definition_specifications/get").as("getDestinationSpecifications"); - - selectServiceType("Local JSON"); - - cy.wait("@getDestinationSpecifications"); - - enterName(name); - enterDestinationPath(destinationPath); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/connectorBuilder.ts b/airbyte-webapp-e2e-tests/cypress/commands/connectorBuilder.ts deleted file mode 100644 index e6c2e8ee17b4b..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/connectorBuilder.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { - addStream, - configureOffsetPagination, - enterName, - enterRecordSelector, - enterStreamName, - enterTestInputs, - enterUrlBase, - enterUrlPath, - goToTestPage, - goToView, - openTestInputs, - selectAuthMethod, - submitForm, - togglePagination -} from "pages/connectorBuilderPage"; - -export const configureGlobals = () => { - goToView("global"); - enterName("Dummy API"); - enterUrlBase("http://dummy_api:6767/"); -} - -export const configureStream = () => { - addStream(); - enterStreamName("Items"); - enterUrlPath("items/"); - submitForm(); - enterRecordSelector("items"); -} - -export const configureAuth = () => { - goToView("global"); - selectAuthMethod("Bearer"); - openTestInputs(); - enterTestInputs({ apiKey: "theauthkey" }) - submitForm(); -} - -export const configurePagination = () => { - goToView("0"); - togglePagination(); - configureOffsetPagination("2", "header", "offset"); -} - -const testPanelContains = (str: string) => { - cy.get("pre").contains(str).should("exist"); -} - -export const assertTestReadAuthFailure = () => { - testPanelContains('"error": "Bad credentials"'); -}; - -export const assertTestReadItems = () => { - testPanelContains('"name": "abc"'); - testPanelContains('"name": "def"'); -}; - -export const assertMultiPageReadItems = () => { - goToTestPage(1); - assertTestReadItems(); - - goToTestPage(2); - testPanelContains('"name": "xxx"'); - testPanelContains('"name": "yyy"'); - - goToTestPage(3); - testPanelContains('[]'); -}; \ No newline at end of file diff --git a/airbyte-webapp-e2e-tests/cypress/commands/db/db.ts b/airbyte-webapp-e2e-tests/cypress/commands/db/db.ts deleted file mode 100644 index fe5524ac60aff..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/db/db.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { - alterCitiesTableQuery, - createCarsTableQuery, - createCitiesTableQuery, - createUsersTableQuery, - dropCarsTableQuery, - dropCitiesTableQuery, - dropUsersTableQuery, - insertCitiesTableQuery, - insertUsersTableQuery, -} from "./queries"; - -/** - * Wrapper for DB Query Cypress task - * @param queryString - */ -export const runDbQuery = (queryString: string) => cy.task("dbQuery", { query: queryString }); - -interface TableExistsResponse { - exists: boolean; -} -/** - * Function for composing the query for checking the existence of a table - * @param tableName - * @return string - */ -const composeIsTableExistQuery = (tableName: string) => - `SELECT EXISTS (SELECT FROM pg_tables - WHERE - schemaname = 'public' AND - tablename = '${tableName}' - )`; - -export const populateDBSource = () => { - runDbQuery(createUsersTableQuery); - runDbQuery(insertUsersTableQuery); - runDbQuery(createCitiesTableQuery); - runDbQuery(insertCitiesTableQuery); -}; - -export const makeChangesInDBSource = () => { - runDbQuery(dropUsersTableQuery); - runDbQuery(alterCitiesTableQuery); - runDbQuery(createCarsTableQuery); -}; - -export const cleanDBSource = () => { - runDbQuery(dropUsersTableQuery); - runDbQuery(dropCitiesTableQuery); - runDbQuery(dropCarsTableQuery); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/db/index.ts b/airbyte-webapp-e2e-tests/cypress/commands/db/index.ts deleted file mode 100644 index 9071a7574a6a8..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/db/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { populateDBSource, makeChangesInDBSource, cleanDBSource } from "./db"; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts b/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts deleted file mode 100644 index a05c742fad39f..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts +++ /dev/null @@ -1,88 +0,0 @@ -export const createTable = (tableName: string, columns: string[]): string => - `CREATE TABLE ${tableName}(${columns.join(", ")});`; - -export const dropTable = (tableName: string) => `DROP TABLE IF EXISTS ${tableName}`; - -export const alterTable = (tableName: string, params: { add?: string[]; drop?: string[] }): string => { - const adds = params.add ? params.add.map((add) => `ADD COLUMN ${add}`) : []; - const drops = params.drop ? params.drop.map((columnName) => `DROP COLUMN ${columnName}`) : []; - const alterations = [...adds, ...drops]; - - return `ALTER TABLE ${tableName} ${alterations.join(", ")};`; -}; - -export const insertIntoTable = (tableName: string, valuesByColumn: Record): string => { - const keys = Object.keys(valuesByColumn); - const values = keys - .map((key) => valuesByColumn[key]) - .map((value) => (typeof value === "string" ? `'${value}'` : value)); - - return `INSERT INTO ${tableName}(${keys.join(", ")}) VALUES(${values.join(", ")});`; -}; - -export const insertMultipleIntoTable = (tableName: string, valuesByColumns: Array>): string => - valuesByColumns.map((valuesByColumn) => insertIntoTable(tableName, valuesByColumn)).join("\n"); - -// Users table -export const createUsersTableQuery = createTable("public.users", [ - "id SERIAL", - "name VARCHAR(200) NULL", - "email VARCHAR(200) NULL", - "updated_at TIMESTAMP", - "CONSTRAINT users_pkey PRIMARY KEY (id)", -]); -export const insertUsersTableQuery = insertMultipleIntoTable("public.users", [ - { name: "Abigail", email: "abigail@example.com", updated_at: "2022-12-19 00:00:00" }, - { name: "Andrew", email: "andrew@example.com", updated_at: "2022-12-19 00:00:00" }, - { name: "Kat", email: "kat@example.com", updated_at: "2022-12-19 00:00:00" }, -]); - -export const dropUsersTableQuery = dropTable("public.users"); - -// Cities table -export const createCitiesTableQuery = createTable("public.cities", ["city_code VARCHAR(8)", "city VARCHAR(200)"]); - -export const insertCitiesTableQuery = insertMultipleIntoTable("public.cities", [ - { - city_code: "BCN", - city: "Barcelona", - }, - { city_code: "MAD", city: "Madrid" }, - { city_code: "VAL", city: "Valencia" }, -]); - -export const alterCitiesTableQuery = alterTable("public.cities", { - add: ["state TEXT", "country TEXT"], - drop: ["city_code"], -}); -export const dropCitiesTableQuery = dropTable("public.cities"); - -// Cars table -export const createCarsTableQuery = createTable("public.cars", [ - "id SERIAL PRIMARY KEY", - "mark VARCHAR(200)", - "model VARCHAR(200)", - "color VARCHAR(200)", -]); - -export const dropCarsTableQuery = dropTable("public.cars"); - -// Dummy tables - used only for populating stream table with a lot of streams(tables) -// NOTE: Not for testing stream functionality! -export const createDummyTablesQuery = (amountOfTables: number) => - Array.from({ length: amountOfTables }, (_, index) => { - const tableName = `public.dummy_table_${index + 1}`; - const columns = [ - "id serial PRIMARY KEY", - "column_1 INTEGER NOT NULL", - "column_2 VARCHAR(100) NOT NULL", - "column_3 DECIMAL(10, 2) NOT NULL", - ]; - return createTable(tableName, columns); - }).join("\n"); - -export const dropDummyTablesQuery = (amountOfTables: number) => { - // postgres doesn't allow to drop multiple tables using wildcard, so need to compose the list of table names - const tables = Array.from({ length: amountOfTables }, (_, index) => `public.dummy_table_${index + 1}`).join(", "); - return dropTable(tables); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/destination.ts b/airbyte-webapp-e2e-tests/cypress/commands/destination.ts deleted file mode 100644 index f52bd8e140813..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/destination.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { deleteEntity, openSettingForm, submitButtonClick, updateField } from "./common"; -import { fillLocalJsonForm, fillPostgresForm } from "./connector"; -import { goToDestinationPage, openNewDestinationForm } from "pages/destinationPage"; - -export const createLocalJsonDestination = (name: string, destinationPath = "/local") => { - cy.intercept("/api/v1/scheduler/destinations/check_connection").as("checkDestinationConnection"); - cy.intercept("/api/v1/destinations/create").as("createDestination"); - - goToDestinationPage(); - openNewDestinationForm(); - fillLocalJsonForm(name, destinationPath); - submitButtonClick(); - - cy.wait("@checkDestinationConnection", { requestTimeout: 8000 }); - cy.wait("@createDestination"); -}; - -export const createPostgresDestination = ( - name: string, - host = "localhost", - port = "5434", - database = "airbyte_ci_destination", - username = "postgres", - password = "secret_password", - schema = "" -) => { - cy.intercept("/api/v1/scheduler/destinations/check_connection").as("checkDestinationConnection"); - cy.intercept("/api/v1/destinations/create").as("createDestination"); - - goToDestinationPage(); - openNewDestinationForm(); - fillPostgresForm(name, host, port, database, username, password, schema); - submitButtonClick(); - - cy.wait("@checkDestinationConnection", { requestTimeout: 8000 }); - cy.wait("@createDestination"); -}; - -export const updateDestination = (name: string, field: string, value: string) => { - cy.intercept("/api/v1/destinations/check_connection_for_update").as("checkDestinationUpdateConnection"); - cy.intercept("/api/v1/destinations/update").as("updateDestination"); - - goToDestinationPage(); - openSettingForm(name); - updateField(field, value); - submitButtonClick(); - - cy.wait("@checkDestinationUpdateConnection"); - cy.wait("@updateDestination"); -}; - -export const deleteDestination = (name: string) => { - cy.intercept("/api/v1/destinations/delete").as("deleteDestination"); - goToDestinationPage(); - openSettingForm(name); - deleteEntity(); - cy.wait("@deleteDestination"); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/interceptors.ts b/airbyte-webapp-e2e-tests/cypress/commands/interceptors.ts deleted file mode 100644 index 0cd74091122a0..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/interceptors.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const interceptGetConnectionRequest = () => - cy.intercept("/api/v1/web_backend/connections/get").as("getConnection"); -export const waitForGetConnectionRequest = () => cy.wait("@getConnection"); - -export const interceptUpdateConnectionRequest = () => - cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); -export const waitForUpdateConnectionRequest = () => cy.wait("@updateConnection", { timeout: 10000 }); - -export const interceptDiscoverSchemaRequest = () => - cy.intercept("/api/v1/sources/discover_schema").as("discoverSchema"); -export const waitForDiscoverSchemaRequest = () => cy.wait("@discoverSchema"); - -export const interceptCreateConnectionRequest = () => - cy.intercept("/api/v1/web_backend/connections/create").as("createConnection"); -export const waitForCreateConnectionRequest = () => cy.wait("@createConnection"); - -export const interceptGetSourcesListRequest = () => cy.intercept("/api/v1/sources/list").as("getSourcesList"); -export const waitForGetSourcesListRequest = () => cy.wait("@getSourcesList"); - -export const interceptGetSourceDefinitionsRequest = () => - cy.intercept("/api/v1/source_definitions/list_for_workspace").as("getSourceDefinitions"); -export const waitForGetSourceDefinitionsRequest = () => cy.wait("@getSourceDefinitions"); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/source.ts b/airbyte-webapp-e2e-tests/cypress/commands/source.ts deleted file mode 100644 index 083ec4e16a570..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/source.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { deleteEntity, openSettingForm, submitButtonClick, updateField } from "./common"; -import { goToSourcePage, openNewSourceForm } from "pages/sourcePage"; -import { fillPostgresForm, fillPokeAPIForm } from "./connector"; - -export const createPostgresSource = ( - name: string, - host = "localhost", - port = "5433", - database = "airbyte_ci_source", - username = "postgres", - password = "secret_password", - schema = "" -) => { - cy.intercept("/api/v1/scheduler/sources/check_connection").as("checkSourceUpdateConnection"); - cy.intercept("/api/v1/sources/create").as("createSource"); - - goToSourcePage(); - openNewSourceForm(); - fillPostgresForm(name, host, port, database, username, password, schema); - submitButtonClick(); - - cy.wait("@checkSourceUpdateConnection", { requestTimeout: 10000 }); - cy.wait("@createSource"); -}; - -export const createPokeApiSource = (name: string, pokeName: string) => { - cy.intercept("/api/v1/scheduler/sources/check_connection").as("checkSourceUpdateConnection"); - cy.intercept("/api/v1/sources/create").as("createSource"); - - goToSourcePage(); - openNewSourceForm(); - fillPokeAPIForm(name, pokeName); - submitButtonClick(); - - cy.wait("@checkSourceUpdateConnection"); - cy.wait("@createSource"); -}; - -export const updateSource = (name: string, field: string, value: string) => { - cy.intercept("/api/v1/sources/check_connection_for_update").as("checkSourceConnection"); - cy.intercept("/api/v1/sources/update").as("updateSource"); - - goToSourcePage(); - openSettingForm(name); - updateField(field, value); - submitButtonClick(); - - cy.wait("@checkSourceConnection"); - cy.wait("@updateSource"); -}; - -export const deleteSource = (name: string) => { - cy.intercept("/api/v1/sources/delete").as("deleteSource"); - goToSourcePage(); - openSettingForm(name); - deleteEntity(); - cy.wait("@deleteSource"); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts b/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts deleted file mode 100644 index 4019d489b2aa5..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const initialSetupCompleted = (completed = true) => { - // Modify the workspaces/list response to mark every workspace as "initialSetupComplete" to ensure we're not showing - // the setup/preference page for any workspace if this method got called. - cy.intercept("POST", "/api/v1/workspaces/get", (req) => { - req.continue((res) => { - res.body.initialSetupComplete = completed; - res.send(res.body); - }); - }); - - cy.on("uncaught:exception", (err, runnable) => { - return false; - }); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/global.d.ts b/airbyte-webapp-e2e-tests/cypress/global.d.ts deleted file mode 100644 index 3f1ee73dee129..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/global.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare global {} diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts deleted file mode 100644 index 32724670b8e05..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { - getConnectionCreateRequest, - getPostgresCreateDestinationBody, - getPostgresCreateSourceBody, - requestCreateConnection, - requestCreateDestination, - requestCreateSource, - requestDeleteConnection, - requestDeleteDestination, - requestDeleteSource, - requestGetConnection, - requestSourceDiscoverSchema, - requestWorkspaceId, -} from "commands/api"; -import { Connection, Destination, Source } from "commands/api/types"; -import { appendRandomString } from "commands/common"; -import { runDbQuery } from "commands/db/db"; -import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; -import { initialSetupCompleted } from "commands/workspaces"; -import { getSyncEnabledSwitch, visitConnectionPage } from "pages/connectionPage"; -import { getManualSyncButton, getSchemaChangeIcon, visitConnectionsListPage } from "pages/connnectionsListPage"; -import { checkCatalogDiffModal, clickCatalogDiffCloseButton } from "pages/modals/catalogDiffModal"; -import { - checkSchemaChangesDetected, - checkSchemaChangesDetectedCleared, - clickSaveReplication, - clickSchemaChangesReviewButton, - searchStream, - selectCursorField, - selectNonBreakingChangesPreference, - selectSyncMode, -} from "pages/replicationPage"; - -describe("Connection - Auto-detect schema changes", () => { - let source: Source; - let destination: Destination; - let connection: Connection; - - beforeEach(() => { - initialSetupCompleted(); - runDbQuery(dropUsersTableQuery); - runDbQuery(createUsersTableQuery); - - requestWorkspaceId().then(() => { - const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Auto-detect schema Source")); - const destinationRequestBody = getPostgresCreateDestinationBody( - appendRandomString("Auto-detect schema Destination") - ); - - requestCreateSource(sourceRequestBody).then((sourceResponse) => { - source = sourceResponse; - requestCreateDestination(destinationRequestBody).then((destinationResponse) => { - destination = destinationResponse; - }); - - requestSourceDiscoverSchema(source.sourceId).then(({ catalog, catalogId }) => { - const connectionRequestBody = getConnectionCreateRequest({ - name: appendRandomString("Auto-detect schema test connection"), - sourceId: source.sourceId, - destinationId: destination.destinationId, - syncCatalog: catalog, - sourceCatalogId: catalogId, - }); - requestCreateConnection(connectionRequestBody).then((connectionResponse) => { - connection = connectionResponse; - }); - }); - }); - }); - }); - - afterEach(() => { - if (connection) { - requestDeleteConnection(connection.connectionId); - } - if (source) { - requestDeleteSource(source.sourceId); - } - if (destination) { - requestDeleteDestination(destination.destinationId); - } - - runDbQuery(dropUsersTableQuery); - }); - - describe("non-breaking changes", () => { - beforeEach(() => { - runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); - requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); - }); - - it("shows non-breaking change on list page", () => { - visitConnectionsListPage(); - getSchemaChangeIcon(connection, "non_breaking").should("exist"); - getManualSyncButton(connection).should("be.enabled"); - }); - - it("shows non-breaking change that can be saved after refresh", () => { - // Need to continue running but async breaks everything - visitConnectionPage(connection, "replication"); - - checkSchemaChangesDetected({ breaking: false }); - clickSchemaChangesReviewButton(); - getSyncEnabledSwitch().should("be.enabled"); - - checkCatalogDiffModal(); - clickCatalogDiffCloseButton(); - - checkSchemaChangesDetectedCleared(); - - clickSaveReplication(); - getSyncEnabledSwitch().should("be.enabled"); - }); - }); - - describe("breaking changes", () => { - beforeEach(() => { - const streamName = "users"; - visitConnectionPage(connection, "replication"); - - // Change users sync mode - searchStream(streamName); - selectSyncMode("Incremental", "Deduped + history"); - selectCursorField(streamName, "updated_at"); - clickSaveReplication(); - - // Remove cursor from db and refreshs schema to force breaking change detection - runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); - requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); - cy.reload(); - }); - - it("shows breaking change on list page", () => { - visitConnectionsListPage(); - getSchemaChangeIcon(connection, "breaking").should("exist"); - getManualSyncButton(connection).should("be.disabled"); - }); - - it("shows breaking change that can be saved after refresh and fix", () => { - visitConnectionPage(connection, "replication"); - - // Confirm that breaking changes are there - checkSchemaChangesDetected({ breaking: true }); - clickSchemaChangesReviewButton(); - getSyncEnabledSwitch().should("be.disabled"); - - checkCatalogDiffModal(); - clickCatalogDiffCloseButton(); - checkSchemaChangesDetectedCleared(); - - // Fix the conflict - searchStream("users"); - selectSyncMode("Full refresh", "Append"); - - clickSaveReplication(); - getSyncEnabledSwitch().should("be.enabled"); - }); - }); - - describe("non-breaking schema update preference", () => { - it("saves non-breaking schema update preference change", () => { - visitConnectionPage(connection, "replication"); - selectNonBreakingChangesPreference("disable"); - - cy.intercept("/api/v1/web_backend/connections/update").as("updatesNonBreakingPreference"); - - clickSaveReplication({ confirm: false }); - - cy.wait("@updatesNonBreakingPreference").then((interception) => { - assert.equal((interception.response?.body as Connection).nonBreakingChangesPreference, "disable"); - }); - }); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/base.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/base.spec.ts deleted file mode 100644 index b4f59dd559d2d..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/base.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -describe("Error handling view", () => { - it("Shows Version Mismatch page", () => { - cy.intercept("/api/v1/**", { - statusCode: 500, - body: { - error: - "Version mismatch between 0.0.1-ci and 0.0.2-ci.\nPlease upgrade or reset your Airbyte Database, see more at https://docs.airbyte.io/operator-guides/upgrading-airbyte", - }, - }); - - cy.on("uncaught:exception", () => false); - - cy.visit("/"); - - cy.get("div").contains("Version mismatch between 0.0.1-ci and 0.0.2-ci.").should("exist"); - }); - - it("Shows Server Unavailable page", () => { - cy.intercept("/api/v1/**", { - statusCode: 502, - body: "Failed to fetch", - }); - - cy.on("uncaught:exception", () => false); - - cy.visit("/"); - - cy.get("div").contains("Cannot reach server. The server may still be starting up.").should("exist"); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts deleted file mode 100644 index 0f9ece580688b..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts +++ /dev/null @@ -1,581 +0,0 @@ -import { appendRandomString, deleteEntity, submitButtonClick } from "commands/common"; -import { createTestConnection } from "commands/connection"; -import { deleteDestination } from "commands/destination"; -import { deleteSource } from "commands/source"; -import { initialSetupCompleted } from "commands/workspaces"; -import { - confirmStreamConfigurationChangedPopup, - selectSchedule, - fillOutDestinationPrefix, - goToReplicationTab, - setupDestinationNamespaceCustomFormat, - checkSuccessResult, - refreshSourceSchemaBtnClick, - resetModalSaveBtnClick, - toggleStreamEnabledState, - searchStream, - selectCursorField, - checkCursorField, - selectSyncMode, - setupDestinationNamespaceDefaultFormat, - checkPrimaryKey, - isPrimaryKeyNonExist, - selectPrimaryKeyField, - checkPreFilledPrimaryKeyField, - checkStreamFields, - expandStreamDetailsByName, -} from "pages/replicationPage"; -import { goToSourcePage, openSourceOverview } from "pages/sourcePage"; -import { goToSettingsPage, openConnectionOverviewByDestinationName } from "pages/settingsConnectionPage"; -import { cleanDBSource, makeChangesInDBSource, populateDBSource } from "commands/db"; -import { - checkCatalogDiffModal, - clickCatalogDiffCloseButton, - newFieldsTable, - newStreamsTable, - removedFieldsTable, - removedStreamsTable, - toggleStreamWithChangesAccordion, -} from "pages/modals/catalogDiffModal"; -import { - interceptGetConnectionRequest, - interceptUpdateConnectionRequest, - waitForGetConnectionRequest, - waitForUpdateConnectionRequest, -} from "commands/interceptors"; - -describe("Connection - creation, updating connection replication settings, deletion", () => { - beforeEach(() => { - initialSetupCompleted(); - - interceptGetConnectionRequest(); - interceptUpdateConnectionRequest(); - }); - - it("Create Postgres <> LocalJSON connection, check it's creation", () => { - const sourceName = appendRandomString("Test connection source cypress"); - const destName = appendRandomString("Test connection destination cypress"); - - createTestConnection(sourceName, destName); - cy.get("div").contains(sourceName).should("exist"); - cy.get("div").contains(destName).should("exist"); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create Postgres <> LocalJSON connection, update connection replication settings - select schedule and add destination prefix", () => { - const sourceName = appendRandomString("Test update connection source cypress"); - const destName = appendRandomString("Test update connection destination cypress"); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - selectSchedule("Every hour"); - fillOutDestinationPrefix("auto_test"); - - submitButtonClick(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it(`Creates PokeAPI <> Local JSON connection, update connection replication settings - - select schedule, add destination prefix, set destination namespace custom format, change prefix and make sure that it's applied to all streams`, () => { - const sourceName = appendRandomString("Test update connection PokeAPI source cypress"); - const destName = appendRandomString("Test update connection Local JSON destination cypress"); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - selectSchedule("Every hour"); - fillOutDestinationPrefix("auto_test"); - setupDestinationNamespaceCustomFormat("_test"); - selectSyncMode("Full refresh", "Append"); - - const prefix = "auto_test"; - fillOutDestinationPrefix(prefix); - - // Ensures the prefix is applied to the streams - assert(cy.get(`[title*="${prefix}"]`)); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - expect(interception.request.method).to.eq("POST"); - expect(interception.request) - .property("body") - .to.contain({ - name: `${sourceName} <> ${destName}Connection name`, - prefix: "auto_test", - namespaceDefinition: "customformat", - namespaceFormat: "${SOURCE_NAMESPACE}_test", - status: "active", - }); - expect(interception.request.body.scheduleData.basicSchedule).to.contain({ - units: 1, - timeUnit: "hours", - }); - - const streamToUpdate = interception.request.body.syncCatalog.streams[0]; - - expect(streamToUpdate.config).to.contain({ - aliasName: "pokemon", - destinationSyncMode: "append", - selected: true, - }); - - expect(streamToUpdate.stream).to.contain({ - name: "pokemon", - }); - expect(streamToUpdate.stream.supportedSyncModes).to.contain("full_refresh"); - }); - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create PokeAPI <> Local JSON connection, update connection replication settings - edit the schedule type one by one - cron, manual, every hour", () => { - const sourceName = appendRandomString("Test connection source cypress PokeAPI"); - const destName = appendRandomString("Test connection destination cypress"); - - createTestConnection(sourceName, destName); - - goToReplicationTab(); - - selectSchedule("Cron"); - submitButtonClick(); - checkSuccessResult(); - - selectSchedule("Manual"); - submitButtonClick(); - checkSuccessResult(); - - selectSchedule("Every hour"); - submitButtonClick(); - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create PokeAPI <> Local JSON connection, update connection replication settings - make sure that saving a connection's schedule type only changes expected values", () => { - const sourceName = appendRandomString("Test update connection PokeAPI source cypress"); - const destName = appendRandomString("Test update connection Local JSON destination cypress"); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - let loadedConnection: any = null; // Should be a WebBackendConnectionRead - waitForGetConnectionRequest().then((interception) => { - const { - scheduleType: readScheduleType, - scheduleData: readScheduleData, - ...connectionRead - } = interception.response?.body; - loadedConnection = connectionRead; - - expect(loadedConnection).not.to.eq(null); - expect(readScheduleType).to.eq("manual"); - expect(readScheduleData).to.eq(undefined); - }); - - goToReplicationTab(); - - selectSchedule("Every hour"); - submitButtonClick(); - - waitForUpdateConnectionRequest().then((interception) => { - // Schedule is pulled out here, but we don't do anything with is as it's legacy - const { scheduleType, scheduleData, schedule, ...connectionUpdate } = interception.response?.body; - expect(scheduleType).to.eq("basic"); - expect(scheduleData.basicSchedule).to.deep.eq({ - timeUnit: "hours", - units: 1, - }); - - expect(loadedConnection).to.deep.eq(connectionUpdate); - }); - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create PokeAPI <> Local JSON connection, and delete connection", () => { - const sourceName = "Test delete connection source cypress"; - const destName = "Test delete connection destination cypress"; - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToSettingsPage(); - - deleteEntity(); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create PokeAPI <> Local JSON connection, update connection replication settings - set destination namespace with 'Custom format' option", () => { - const sourceName = appendRandomString("Test update connection PokeAPI source cypress"); - const destName = appendRandomString("Test update connection Local JSON destination cypress"); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - const namespace = "_DestinationNamespaceCustomFormat"; - setupDestinationNamespaceCustomFormat(namespace); - - // Ensures the DestinationNamespace is applied to the streams - assert(cy.get(`[title*="${namespace}"]`)); - - submitButtonClick(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - expect(interception.request.method).to.eq("POST"); - expect(interception.request) - .property("body") - .to.contain({ - name: `${sourceName} <> ${destName}Connection name`, - namespaceDefinition: "customformat", - namespaceFormat: "${SOURCE_NAMESPACE}_DestinationNamespaceCustomFormat", - status: "active", - }); - - const streamToUpdate = interception.request.body.syncCatalog.streams[0]; - - expect(streamToUpdate.stream).to.contain({ - name: "pokemon", - }); - }); - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create PokeAPI <> Local JSON connection, update connection replication settings - set destination namespace with 'Mirror source structure' option", () => { - const sourceName = appendRandomString("Test update connection PokeAPI source cypress"); - const destName = appendRandomString("Test update connection Local JSON destination cypress"); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - const namespace = ""; - - // Ensures the DestinationNamespace is applied to the streams - assert(cy.get(`[title*="${namespace}"]`)); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create PokeAPI <> Local JSON connection, update connection replication settings - set destination namespace with 'Destination default' option", () => { - const sourceName = appendRandomString("Test update connection PokeAPI source cypress"); - const destName = appendRandomString("Test update connection Local JSON destination cypress"); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - setupDestinationNamespaceDefaultFormat(); - - const namespace = ""; - - // Ensures the DestinationNamespace is applied to the streams - assert(cy.get(`[title*="${namespace}"]`)); - - submitButtonClick(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - expect(interception.request.method).to.eq("POST"); - expect(interception.request) - .property("body") - .to.contain({ - name: `${sourceName} <> ${destName}Connection name`, - namespaceDefinition: "destination", - namespaceFormat: "${SOURCE_NAMESPACE}", - status: "active", - }); - - const streamToUpdate = interception.request.body.syncCatalog.streams[0]; - - expect(streamToUpdate.stream).to.contain({ - name: "pokemon", - }); - }); - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); -}); - -describe("Connection - stream details", () => { - beforeEach(() => { - initialSetupCompleted(); - populateDBSource(); - }); - - afterEach(() => { - cleanDBSource(); - }); - - it("Create Postgres <> Postgres connection, connection replication settings, expand stream details", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - const streamName = "users"; - - const collectionNames = ["email", "id", "name", "updated_at"]; - const collectionTypes = ["String", "Integer", "String", "Datetime"]; - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream(streamName); - expandStreamDetailsByName(streamName); - checkStreamFields(collectionNames, collectionTypes); - - deleteSource(sourceName); - deleteDestination(destName); - }); -}); - -describe("Connection sync modes", () => { - beforeEach(() => { - initialSetupCompleted(); - populateDBSource(); - - interceptUpdateConnectionRequest(); - }); - - afterEach(() => { - cleanDBSource(); - }); - - it("Create Postgres <> Postgres connection, update connection replication settings - select 'Incremental Append' sync mode, select required Cursor field, verify changes", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - const streamName = "users"; - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream(streamName); - selectSyncMode("Incremental", "Append"); - selectCursorField(streamName, "updated_at"); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream("users"); - checkCursorField(streamName, "updated_at"); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create Postgres <> Postgres connection, update connection replication settings - select 'Incremental Deduped History'(PK is defined), select Cursor field, verify changes", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - const streamName = "users"; - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream(streamName); - selectSyncMode("Incremental", "Deduped + history"); - selectCursorField(streamName, "updated_at"); - checkPreFilledPrimaryKeyField(streamName, "id"); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream(streamName); - - checkCursorField(streamName, "updated_at"); - checkPreFilledPrimaryKeyField(streamName, "id"); - - deleteSource(sourceName); - deleteDestination(destName); - }); - - it("Create Postgres <> Postgres connection, update connection replication settings - select 'Incremental Deduped History'(PK is NOT defined), select Cursor field, select PK, verify changes", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - const streamName = "cities"; - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream(streamName); - selectSyncMode("Incremental", "Deduped + history"); - selectCursorField(streamName, "city"); - isPrimaryKeyNonExist(streamName); - selectPrimaryKeyField(streamName, ["city_code"]); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - goToSourcePage(); - openSourceOverview(sourceName); - openConnectionOverviewByDestinationName(destName); - - goToReplicationTab(); - - searchStream(streamName); - - checkCursorField(streamName, "city"); - checkPrimaryKey(streamName, ["city_code"]); - - deleteSource(sourceName); - deleteDestination(destName); - }); -}); - -describe("Connection - detect source schema changes in source", () => { - beforeEach(() => { - initialSetupCompleted(); - populateDBSource(); - - interceptUpdateConnectionRequest(); - }); - - afterEach(() => { - cleanDBSource(); - }); - - it("Create Postgres <> Local JSON connection, update data in source (async), refresh source schema, check diff modal, reset streams", () => { - const sourceName = appendRandomString( - "Test refresh source schema with changed data - connection Postgres source cypress" - ); - const destName = appendRandomString( - "Test refresh source schema with changed data - connection Local JSON destination cypress" - ); - - createTestConnection(sourceName, destName); - cy.get("div").contains(sourceName).should("exist"); - cy.get("div").contains(destName).should("exist"); - - makeChangesInDBSource(); - goToReplicationTab(); - refreshSourceSchemaBtnClick(); - - checkCatalogDiffModal(); - - cy.get(removedStreamsTable).should("contain", "users"); - - cy.get(newStreamsTable).should("contain", "cars"); - - toggleStreamWithChangesAccordion("cities"); - cy.get(removedFieldsTable).should("contain", "city_code"); - cy.get(newFieldsTable).children().should("contain", "country").and("contain", "state"); - - clickCatalogDiffCloseButton(); - - toggleStreamEnabledState("cars"); - - submitButtonClick(); - resetModalSaveBtnClick(); - - waitForUpdateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection/streamTable.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection/streamTable.spec.ts deleted file mode 100644 index 8b88d911469e1..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection/streamTable.spec.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { initialSetupCompleted } from "commands/workspaces"; -import { - getPostgresCreateDestinationBody, - getPostgresCreateSourceBody, - requestCreateDestination, - requestCreateSource, - requestDeleteConnection, - requestDeleteDestination, - requestDeleteSource, - requestWorkspaceId, -} from "commands/api"; -import { appendRandomString, submitButtonClick } from "commands/common"; -import { clickNewConnectionButton, visitConnectionsListPage } from "pages/connnectionsListPage"; -import { - checkAmountOfStreamTableRows, - checkColumnNames, - checkConnectorIconAndTitle, - clickUseExistingConnectorButton, - isAtConnectionOverviewPage, - isAtNewConnectionPage, - isNewConnectionPageHeaderVisible, - isStreamTableRowVisible, - scrollTableToStream, - selectExistingConnectorFromDropdown, -} from "pages/newConnectionPage"; -import { - interceptCreateConnectionRequest, - interceptDiscoverSchemaRequest, - interceptGetSourceDefinitionsRequest, - interceptGetSourcesListRequest, - waitForCreateConnectionRequest, - waitForDiscoverSchemaRequest, - waitForGetSourceDefinitionsRequest, - waitForGetSourcesListRequest, -} from "commands/interceptors"; -import { Connection, Destination, Source } from "commands/api/types"; -import { clearStreamSearch, searchStream, selectSchedule } from "pages/replicationPage"; -import { runDbQuery } from "commands/db/db"; -import { - createUsersTableQuery, - dropUsersTableQuery, - createDummyTablesQuery, - dropDummyTablesQuery, -} from "commands/db/queries"; - -// TODO: Enable this test when the new stream table will be turned on -describe.skip("New stream table - new connection set up ", () => { - let source: Source; - let destination: Destination; - let connectionId: string; - - before(() => { - initialSetupCompleted(); - runDbQuery(dropUsersTableQuery); - runDbQuery(dropDummyTablesQuery(20)); - - runDbQuery(createUsersTableQuery); - runDbQuery(createDummyTablesQuery(20)); - - requestWorkspaceId().then(() => { - const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Stream table Source")); - const destinationRequestBody = getPostgresCreateDestinationBody(appendRandomString("Stream table Destination")); - - requestCreateSource(sourceRequestBody).then((sourceResponse) => { - source = sourceResponse; - requestCreateDestination(destinationRequestBody).then((destinationResponse) => { - destination = destinationResponse; - }); - }); - }); - }); - - after(() => { - if (connectionId) { - requestDeleteConnection(connectionId); - } - if (source) { - requestDeleteSource(source.sourceId); - } - if (destination) { - requestDeleteDestination(destination.destinationId); - } - }); - - it("should open 'New connection' page", () => { - visitConnectionsListPage(); - interceptGetSourcesListRequest(); - interceptGetSourceDefinitionsRequest(); - - clickNewConnectionButton(); - waitForGetSourcesListRequest(); - waitForGetSourceDefinitionsRequest(); - }); - - it("should select existing Source from dropdown and click button", () => { - selectExistingConnectorFromDropdown(source.name); - clickUseExistingConnectorButton("source"); - }); - - it("should select existing Destination from dropdown and click button", () => { - interceptDiscoverSchemaRequest(); - selectExistingConnectorFromDropdown(destination.name); - clickUseExistingConnectorButton("destination"); - waitForDiscoverSchemaRequest(); - }); - - it("should redirect to 'New connection' settings page with stream table'", () => { - isAtNewConnectionPage(); - }); - - it("should show 'New connection' page header", () => { - isNewConnectionPageHeaderVisible(); - }); - - it("should set 'Replication frequency' to 'Manual'", () => { - selectSchedule("Manual"); - }); - - it("should check check connector icons and titles in table", () => { - checkConnectorIconAndTitle("source"); - checkConnectorIconAndTitle("destination"); - }); - - it("should check columns names in table", () => { - checkColumnNames(); - }); - - it("should check total amount of table streams", () => { - // dummy tables amount + users table - checkAmountOfStreamTableRows(21); - }); - - it("should allow to scroll table to desired stream table row and it should be visible", () => { - const desiredStreamTableRow = "dummy_table_18"; - - scrollTableToStream(desiredStreamTableRow); - isStreamTableRowVisible(desiredStreamTableRow); - }); - - it("should filter table by stream name", () => { - searchStream("dummy_table_10"); - checkAmountOfStreamTableRows(1); - }); - - it("should clear stream search input field and show all available streams", () => { - clearStreamSearch(); - checkAmountOfStreamTableRows(21); - }); - - /* - here will be added more tests to extend the test flow - */ - - it("should set up a connection", () => { - interceptCreateConnectionRequest(); - submitButtonClick(true); - waitForCreateConnectionRequest().then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - expect(interception.request.method).to.eq("POST"); - - const connection: Partial = { - name: `${source.name} <> ${destination.name}`, - scheduleType: "manual", - }; - expect(interception.request.body).to.contain(connection); - expect(interception.response?.body).to.contain(connection); - - connectionId = interception.response?.body?.connectionId; - }); - }); - - it("should redirect to connection overview page after connection set up", () => { - isAtConnectionOverviewPage(connectionId); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connectorBuilder.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connectorBuilder.spec.ts deleted file mode 100644 index c719ed6df81df..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/connectorBuilder.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { goToConnectorBuilderPage, startFromScratch, testStream } from "pages/connectorBuilderPage"; -import { - assertTestReadItems, - assertTestReadAuthFailure, - configureAuth, - configureGlobals, - configureStream, - configurePagination, - assertMultiPageReadItems, -} from "commands/connectorBuilder"; -import { initialSetupCompleted } from "commands/workspaces"; - -describe("Connector builder", () => { - before(() => { - initialSetupCompleted(); - goToConnectorBuilderPage(); - startFromScratch(); - }); - - it("Configure basic connector", () => { - configureGlobals(); - configureStream(); - }); - - it("Fail on missing auth", () => { - testStream(); - assertTestReadAuthFailure(); - }); - - it("Succeed on provided auth", () => { - configureAuth(); - testStream(); - assertTestReadItems(); - }); - - it("Pagination", () => { - configurePagination(); - testStream(); - assertMultiPageReadItems(); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts deleted file mode 100644 index 26fd9109a07be..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { appendRandomString } from "commands/common"; -import { createLocalJsonDestination, deleteDestination, updateDestination } from "commands/destination"; -import { initialSetupCompleted } from "commands/workspaces"; - -describe("Destination main actions", () => { - beforeEach(() => { - initialSetupCompleted(); - }); - - it("Create new destination", () => { - createLocalJsonDestination("Test destination cypress", "/local"); - - cy.url().should("include", `/destination/`); - }); - - it("Update destination", () => { - const destName = appendRandomString("Test destination cypress for update"); - createLocalJsonDestination(destName, "/local"); - updateDestination(destName, "connectionConfiguration.destination_path", "/local/my-json"); - - cy.get("div[data-id='success-result']").should("exist"); - cy.get("input[value='/local/my-json']").should("exist"); - }); - - it("Delete destination", () => { - const destName = appendRandomString("Test destination cypress for delete"); - createLocalJsonDestination(destName, "/local"); - deleteDestination(destName); - - cy.visit("/destination"); - cy.get("div").contains(destName).should("not.exist"); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/onboarding.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/onboarding.spec.ts deleted file mode 100644 index 2ea56269f4434..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/onboarding.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { submitButtonClick, fillEmail } from "commands/common"; -import { initialSetupCompleted } from "commands/workspaces"; - -describe("Preferences actions", () => { - beforeEach(() => { - initialSetupCompleted(false); - }); - - it("Should redirect to connections page after email is entered", () => { - cy.visit("/preferences"); - cy.url().should("include", `/preferences`); - - fillEmail("test-email-onboarding@test-onboarding-domain.com"); - cy.get("input[name=securityUpdates]").parent().click(); - - submitButtonClick(); - - cy.url().should("match", /.*\/connections/); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts deleted file mode 100644 index 995039304486e..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { appendRandomString, submitButtonClick } from "commands/common"; -import { createPostgresSource, deleteSource, updateSource } from "commands/source"; -import { initialSetupCompleted } from "commands/workspaces"; -import { goToSourcePage, openNewSourceForm } from "pages/sourcePage"; -import { openHomepage } from "pages/sidebar"; -import { selectServiceType } from "pages/createConnectorPage"; -import { fillPokeAPIForm } from "commands/connector"; - -describe("Source main actions", () => { - beforeEach(() => initialSetupCompleted()); - - it("Create new source", () => { - cy.intercept("/api/v1/sources/create").as("createSource"); - createPostgresSource("Test source cypress"); - - cy.wait("@createSource", { timeout: 30000 }).then((interception) => { - assert("include", `/source/${interception.response?.body.Id}`); - }); - }); - - // TODO: add update source on some other connector or create 1 more user for pg - it.skip("Update source", () => { - const sourceName = appendRandomString("Test source cypress for update"); - createPostgresSource(sourceName); - updateSource(sourceName, "connectionConfiguration.start_date", "2020-11-11"); - - cy.get("div[data-id='success-result']").should("exist"); - cy.get("input[value='2020-11-11']").should("exist"); - }); - - it("Delete source", () => { - const sourceName = appendRandomString("Test source cypress for delete"); - createPostgresSource(sourceName); - deleteSource(sourceName); - - cy.visit("/"); - cy.get("div").contains(sourceName).should("not.exist"); - }); -}); - -describe("Unsaved changes modal", () => { - beforeEach(() => initialSetupCompleted()); - - it("Check leaving Source page without any changes", () => { - goToSourcePage(); - openNewSourceForm(); - - openHomepage(); - - cy.url().should("include", "/connections"); - cy.get("[data-testid='confirmationModal']").should("not.exist"); - }); - - it("Check leaving Source page without any changes after selection type", () => { - goToSourcePage(); - openNewSourceForm(); - selectServiceType("PokeAPI"); - - openHomepage(); - - cy.url().should("include", "/connections"); - cy.get("[data-testid='confirmationModal']").should("not.exist"); - }); - - it("Check leaving Source page without any changes", () => { - goToSourcePage(); - openNewSourceForm(); - fillPokeAPIForm("testName", "ditto"); - - openHomepage(); - - cy.get("[data-testid='confirmationModal']").should("exist"); - cy.get("[data-testid='confirmationModal']").contains("Discard changes"); - cy.get("[data-testid='confirmationModal']").contains( - "There are unsaved changes. Are you sure you want to discard your changes?" - ); - }); - - it("Check leaving Source page after failing testing", () => { - cy.intercept("/api/v1/scheduler/sources/check_connection").as("checkSourceUpdateConnection"); - - goToSourcePage(); - openNewSourceForm(); - fillPokeAPIForm("testName", "name"); - submitButtonClick(); - - cy.wait("@checkSourceUpdateConnection", { timeout: 5000 }); - - openHomepage(); - - cy.get("[data-testid='confirmationModal']").should("exist"); - cy.get("[data-testid='confirmationModal']").contains("Discard changes"); - cy.get("[data-testid='confirmationModal']").contains( - "There are unsaved changes. Are you sure you want to discard your changes?" - ); - }); -}); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts deleted file mode 100644 index f901c448d8dab..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Connection } from "commands/api/types"; -import { getWorkspaceId } from "commands/api/workspace"; - -const syncEnabledSwitch = "[data-testid='enabledControl-switch']"; - -export const visitConnectionPage = (connection: Connection, tab = "") => { - cy.intercept("**/web_backend/connections/get").as("getConnection"); - cy.visit(`/workspaces/${getWorkspaceId()}/connections/${connection.connectionId}/${tab}`); - cy.wait("@getConnection", { timeout: 20000 }); -}; - -export const getSyncEnabledSwitch = () => cy.get(syncEnabledSwitch); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connectorBuilderPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connectorBuilderPage.ts deleted file mode 100644 index ec8e025523af3..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/connectorBuilderPage.ts +++ /dev/null @@ -1,96 +0,0 @@ -const startFromScratchButton = "button[data-testid='start-from-scratch']"; -const nameInput = "input[name='global.connectorName']"; -const urlBaseInput = "input[name='global.urlBase']"; -const addStreamButton = "button[data-testid='add-stream']"; -const apiKeyInput = "input[name='connectionConfiguration.api_key']"; -const toggleInput = "input[data-testid='toggle']"; -const streamNameInput = "input[name='streamName']"; -const streamUrlPath = "input[name='urlPath']"; -const recordSelectorInput = "[data-testid='tag-input'] input"; -const authType = "[data-testid='global.authenticator.type']"; -const testInputsButton = "[data-testid='test-inputs']"; -const limitInput = "[name='streams[0].paginator.strategy.page_size']"; -const injectOffsetInto = "[data-testid$='paginator.pageTokenOption.inject_into']"; -const injectOffsetFieldName = "[name='streams[0].paginator.pageTokenOption.field_name']"; -const testPageItem = "[data-testid='test-pages'] li"; -const submit = "button[type='submit']"; -const testStreamButton = "button[data-testid='read-stream']"; - -export const goToConnectorBuilderPage = () => { - cy.visit("/connector-builder"); - cy.wait(3000); -}; - -export const startFromScratch = () => { - cy.get(startFromScratchButton).click(); -}; - -export const enterName = (name: string) => { - cy.get(nameInput).clear().type(name); -}; - -export const enterUrlBase = (urlBase: string) => { - cy.get(urlBaseInput).type(urlBase); -}; - -export const enterRecordSelector = (recordSelector: string) => { - cy.get(recordSelectorInput).first().type(recordSelector, { force: true }).type("{enter}", { force: true }); -}; - -const selectFromDropdown = (selector: string, value: string) => { - cy.get(`${selector} .react-select__dropdown-indicator`).last().click({ force: true }); - - cy.get(`.react-select__option`).contains(value).click(); -}; - -export const selectAuthMethod = (value: string) => { - selectFromDropdown(authType, value); -}; - -export const goToView = (view: string) => { - cy.get(`button[data-testid=navbutton-${view}]`).click(); -}; - -export const openTestInputs = () => { - cy.get(testInputsButton).click(); -}; - -export const enterTestInputs = ({ apiKey }: { apiKey: string }) => { - cy.get(apiKeyInput).type(apiKey); -}; - -export const goToTestPage = (page: number) => { - cy.get(testPageItem).contains(page).click(); -}; - -export const togglePagination = () => { - cy.get(toggleInput).first().click({ force: true }); -}; - -export const configureOffsetPagination = (limit: string, into: string, fieldName: string) => { - cy.get(limitInput).type(limit); - selectFromDropdown(injectOffsetInto, into); - cy.get(injectOffsetFieldName).type(fieldName); -}; - -export const addStream = () => { - cy.get(addStreamButton).click(); -}; - -export const enterStreamName = (streamName: string) => { - cy.get(streamNameInput).type(streamName); -}; - -export const enterUrlPath = (urlPath: string) => { - cy.get(streamUrlPath).type(urlPath); -}; - -export const submitForm = () => { - cy.get(submit).click(); -}; - -export const testStream = () => { - // wait for debounced form - cy.wait(500); - cy.get(testStreamButton).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts deleted file mode 100644 index bb468f1b26732..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Connection } from "commands/api/types"; -import { getWorkspaceId } from "commands/api/workspace"; - -const statusCell = (connectionId: string) => `[data-testId='statusCell-${connectionId}']`; -const changesStatusIcon = (type: string) => `[data-testId='changesStatusIcon-${type}']`; -const manualSyncButton = "button[data-testId='manual-sync-button']"; -const newConnectionButton = "button[data-testId='new-connection-button']"; - -export const visitConnectionsListPage = () => { - cy.intercept("**/web_backend/connections/list").as("listConnections"); - cy.visit(`/workspaces/${getWorkspaceId()}/connections`); - cy.wait("@listConnections", { timeout: 20000 }); -}; - -export const getSchemaChangeIcon = (connection: Connection, type: "breaking" | "non_breaking") => - cy.get(`${statusCell(connection.connectionId)} ${changesStatusIcon(type)}`); - -export const getManualSyncButton = (connection: Connection) => - cy.get(`${statusCell(connection.connectionId)} ${manualSyncButton}`); - -export const clickNewConnectionButton = () => { - cy.get(newConnectionButton).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/createConnectorPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/createConnectorPage.ts deleted file mode 100644 index 44bee2632352e..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/createConnectorPage.ts +++ /dev/null @@ -1,63 +0,0 @@ -const selectTypeDropdown = "div[data-testid='serviceType']"; -const getServiceTypeDropdownOption = (serviceName: string) => `div[data-testid='${serviceName}']`; -const nameInput = "input[name=name]"; -const hostInput = "input[name='connectionConfiguration.host']"; -const portInput = "input[name='connectionConfiguration.port']"; -const databaseInput = "input[name='connectionConfiguration.database']"; -const usernameInput = "input[name='connectionConfiguration.username']"; -const passwordInput = "input[name='connectionConfiguration.password']"; -const pokemonNameInput = "input[name='connectionConfiguration.pokemon_name']"; -const schemaInput = "[data-testid='tag-input'] input"; -const destinationPathInput = "input[name='connectionConfiguration.destination_path']"; - -export const selectServiceType = (type: string) => - cy - .get(selectTypeDropdown) - .click() - .within(() => cy.get(getServiceTypeDropdownOption(type)).click()); - -export const enterName = (name: string) => { - cy.get(nameInput).clear().type(name); -}; - -export const enterHost = (host: string) => { - cy.get(hostInput).type(host); -}; - -export const enterPort = (port: string) => { - cy.get(portInput).type("{selectAll}{del}").type(port); -}; - -export const enterDatabase = (database: string) => { - cy.get(databaseInput).type(database); -}; - -export const enterUsername = (username: string) => { - cy.get(usernameInput).type(username); -}; - -export const enterPassword = (password: string) => { - cy.get(passwordInput).type(password); -}; - -export const enterPokemonName = (pokeName: string) => { - cy.get(pokemonNameInput).type(pokeName); -}; - -export const enterDestinationPath = (destinationPath: string) => { - cy.get(destinationPathInput).type(destinationPath); -}; - -export const enterSchema = (value: string) => { - if (!value) { - return; - } - cy.get(schemaInput).first().type(value, { force: true }).type("{enter}", { force: true }); -}; - -export const removeSchema = (value = "Remove public") => { - if (!value) { - return; - } - cy.get(`[aria-label*="${value}"]`).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/destinationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/destinationPage.ts deleted file mode 100644 index b217d99dad8e0..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/destinationPage.ts +++ /dev/null @@ -1,21 +0,0 @@ -const newDestination = "button[data-id='new-destination']"; -const addSourceButton = "button[data-testid='select-source']"; - -export const goToDestinationPage = () => { - cy.intercept("/api/v1/destinations/list").as("getDestinationsList"); - cy.visit("/destination"); - cy.wait(3000); -}; - -export const openNewDestinationForm = () => { - cy.wait("@getDestinationsList").then(({ response }) => { - if (response?.body.destinations.length) { - cy.get(newDestination).click(); - } - }); - cy.url().should("include", `/destination/new-destination`); -}; - -export const openAddSource = () => { - cy.get(addSourceButton).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts b/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts deleted file mode 100644 index 4abcf8891b3d3..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const catalogDiffModal = "[data-testid='catalog-diff-modal']"; -export const removedStreamsTable = "table[aria-label='removed streams table']"; -export const newStreamsTable = "table[aria-label='new streams table']"; -const streamWithChangesToggleBtn = (streamName: string) => - `button[data-testid='toggle-accordion-${streamName}-stream']`; -export const removedFieldsTable = "table[aria-label='removed fields']"; -export const newFieldsTable = "table[aria-label='new fields']"; -export const closeButton = "[data-testid='update-schema-confirm-btn']"; - -export const checkCatalogDiffModal = () => { - cy.get(catalogDiffModal).should("exist"); -}; - -export const toggleStreamWithChangesAccordion = (streamName: string) => { - cy.get(streamWithChangesToggleBtn(streamName)).click(); -}; - -export const clickCatalogDiffCloseButton = () => { - cy.get(closeButton).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/newConnectionPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/newConnectionPage.ts deleted file mode 100644 index 34c3209f7a414..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/newConnectionPage.ts +++ /dev/null @@ -1,70 +0,0 @@ -type ConnectorType = "source" | "destination"; -const existingConnectorDropdown = `div[data-testid='entityId']`; -const getExistingConnectorDropdownOption = (connectorName: string) => `div[data-testid='${connectorName}']`; -const useExistingConnectorButton = (connectorType: ConnectorType) => - `button[data-testid='use-existing-${connectorType}-button']`; - -const pageHeaderContainer = `div[data-testid='page-header-container']`; -const newConnectionPageTitle = "New connection"; - -const connectorHeaderGroupIcon = (connectorType: ConnectorType) => - `span[data-testid='connector-header-group-icon-container-${connectorType}']`; -const catalogTreeTableHeader = `div[data-testid='catalog-tree-table-header']`; -const catalogTreeTableBody = `div[data-testid='catalog-tree-table-body']`; - -export const selectExistingConnectorFromDropdown = (connectorName: string) => - cy - .get(existingConnectorDropdown) - .click() - .within(() => cy.get(getExistingConnectorDropdownOption(connectorName)).click()); - -export const clickUseExistingConnectorButton = (connectorType: ConnectorType) => - cy.get(useExistingConnectorButton(connectorType)).click(); - -export const isNewConnectionPageHeaderVisible = () => - cy.get(pageHeaderContainer).contains(newConnectionPageTitle).should("be.visible"); - -/* - Route checking - */ -export const isAtNewConnectionPage = () => cy.url().should("include", `/connections/new-connection`); -export const isAtConnectionOverviewPage = (connectionId: string) => - cy.url().should("include", `connections/${connectionId}/status`); - -/* - Stream table - */ -export const checkConnectorIconAndTitle = (connectorType: ConnectorType) => { - const connectorIcon = connectorHeaderGroupIcon(connectorType); - cy.get(connectorIcon) - .contains(connectorType, { matchCase: false }) - .within(() => { - cy.get("img").should("have.attr", "src").should("not.be.empty"); - }); -}; - -export const checkColumnNames = () => { - const columnNames = ["Sync", "Namespace", "Stream name", "Sync mode", "Cursor field", "Primary key"]; - cy.get(catalogTreeTableHeader).within(($header) => { - columnNames.forEach((columnName) => { - cy.contains(columnName); - }); - // we have two Namespace columns - cy.get(`div:contains(${columnNames[1]})`).should("have.length", 2); - // we have two Stream Name columns - cy.get(`div:contains(${columnNames[2]})`).should("have.length", 2); - }); -}; - -export const checkAmountOfStreamTableRows = (expectedAmountOfRows: number) => - cy - .get(catalogTreeTableBody) - .find("[data-testid^='catalog-tree-table-row-']") - .should("have.length", expectedAmountOfRows); - -export const scrollTableToStream = (streamName: string) => { - cy.get(catalogTreeTableBody).contains(streamName).scrollIntoView(); -}; - -export const isStreamTableRowVisible = (streamName: string) => - cy.get(catalogTreeTableBody).contains(streamName).should("be.visible"); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts deleted file mode 100644 index 3c55b5bf853f3..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { submitButtonClick } from "commands/common"; - -const scheduleDropdown = "div[data-testid='scheduleData']"; -const scheduleValue = (value: string) => `div[data-testid='${value}']`; -const destinationPrefix = "input[data-testid='prefixInput']"; -const replicationTab = "div[data-id='replication-step']"; -const destinationNamespace = "div[data-testid='namespaceDefinition']"; -const destinationNamespaceCustom = "div[data-testid='namespaceDefinition-customformat']"; -const destinationNamespaceDefault = "div[data-testid='namespaceDefinition-destination']"; -const destinationNamespaceSource = "div[data-testid='namespaceDefinition-source']"; -const destinationNamespaceCustomInput = "input[data-testid='input']"; -const syncModeDropdown = "div[data-testid='syncSettingsDropdown'] input"; -const getFieldDropdownContainer = (streamName: string, type: Dropdown) => `div[id='${streamName}_${type}_pathPopout']`; -const getFieldDropdownButton = (streamName: string, type: Dropdown) => - `button[data-testid='${streamName}_${type}_pathPopout']`; -const getFieldDropdownOption = (value: string) => `div[data-testid='${value}']`; -const dropDownOverlayContainer = "div[data-testid='overlayContainer']"; -const streamNameCell = "[data-testid='nameCell']"; -const streamDataTypeCell = "[data-testid='dataTypeCell']"; -const getExpandStreamArrowBtn = (streamName: string) => `[data-testid='${streamName}_expandStreamDetails']`; -const getPreFilledPrimaryKeyText = (streamName: string) => `[data-testid='${streamName}_primaryKey_pathPopout_text']`; -const successResult = "div[data-id='success-result']"; -const resetModalResetCheckbox = "[data-testid='resetModal-reset-checkbox']"; -const saveStreamChangesButton = "button[data-testid='resetModal-save']"; -const connectionNameInput = "input[data-testid='connectionName']"; -const refreshSourceSchemaButton = "button[data-testid='refresh-source-schema-btn']"; -const streamSyncEnabledSwitch = (streamName: string) => `[data-testid='${streamName}-stream-sync-switch']`; -const streamNameInput = "input[data-testid='input']"; -const resetModalSaveButton = "[data-testid='resetModal-save']"; -const schemaChangesDetectedBanner = "[data-testid='schemaChangesDetected']"; -const schemaChangesReviewButton = "[data-testid='schemaChangesReviewButton']"; -const schemaChangesBackdrop = "[data-testid='schemaChangesBackdrop']"; -const nonBreakingChangesPreference = "[data-testid='nonBreakingChangesPreference']"; -const nonBreakingChangesPreferenceValue = (value: string) => `div[data-testid='nonBreakingChangesPreference-${value}']`; - -export const goToReplicationTab = () => { - cy.get(replicationTab).click(); -}; - -export const enterConnectionName = (name: string) => { - cy.get(connectionNameInput).type(name); -}; - -export const expandStreamDetailsByName = (streamName: string) => cy.get(getExpandStreamArrowBtn(streamName)).click(); - -export const selectSchedule = (value: string) => { - cy.get(scheduleDropdown).click(); - cy.get(scheduleValue(value)).click(); -}; - -export const fillOutDestinationPrefix = (value: string) => { - cy.get(destinationPrefix).clear().type(value).should("have.value", value); -}; - -export const setupDestinationNamespaceCustomFormat = (value: string) => { - cy.get(destinationNamespace).click(); - cy.get(destinationNamespaceCustom).click(); - cy.get(destinationNamespaceCustomInput).first().type(value).should("have.value", `\${SOURCE_NAMESPACE}${value}`); -}; - -export const setupDestinationNamespaceSourceFormat = () => { - cy.get(destinationNamespace).click(); - cy.get(destinationNamespaceSource).click(); -}; - -export const refreshSourceSchemaBtnClick = () => cy.get(refreshSourceSchemaButton).click(); - -export const resetModalSaveBtnClick = () => cy.get(resetModalSaveButton).click(); - -export const setupDestinationNamespaceDefaultFormat = () => { - cy.get(destinationNamespace).click(); - cy.get(destinationNamespaceDefault).click(); -}; - -export const selectSyncMode = (source: string, dest: string) => { - cy.get(syncModeDropdown).first().click({ force: true }); - - cy.get(`.react-select__option`).contains(`Source:${source}|Dest:${dest}`).click(); -}; - -type Dropdown = "cursor" | "primaryKey"; -/** - * General function - select dropdown option(s) - * @param streamName - * @param dropdownType - * @param value - */ -const selectFieldDropdownOption = (streamName: string, dropdownType: Dropdown, value: string | string[]) => { - const container = getFieldDropdownContainer(streamName, dropdownType); - const button = getFieldDropdownButton(streamName, dropdownType); - - cy.get(container).within(() => { - cy.get(button).click(); - - if (Array.isArray(value)) { - // in case if multiple options need to be selected - value.forEach((v) => cy.get(getFieldDropdownOption(v)).click()); - } else { - // in case if one option need to be selected - cy.get(getFieldDropdownOption(value)).click(); - } - }); - // close dropdown - // (dropdown need to be closed manually by clicking on overlay in case if multiple option selection is available) - cy.get("body").then(($body) => { - if ($body.find(dropDownOverlayContainer).length > 0) { - cy.get(dropDownOverlayContainer).click(); - } - }); -}; - -/** - * Select cursor value from cursor dropdown(pathPopout) in desired stream - * @param streamName - * @param cursorValue - */ -export const selectCursorField = (streamName: string, cursorValue: string) => - selectFieldDropdownOption(streamName, "cursor", cursorValue); - -/** - * Select primary key value(s) from primary key dropdown(pathPopout) in desired stream - * @param streamName - * @param primaryKeyValues - */ -export const selectPrimaryKeyField = (streamName: string, primaryKeyValues: string[]) => - selectFieldDropdownOption(streamName, "primaryKey", primaryKeyValues); - -export const checkStreamFields = (listNames: string[], listTypes: string[]) => { - cy.get(streamNameCell).each(($span, i) => { - expect($span.text()).to.equal(listNames[i]); - }); - - cy.get(streamDataTypeCell).each(($span, i) => { - expect($span.text()).to.equal(listTypes[i]); - }); -}; - -/** - * General function - check selected field dropdown option or options - * @param streamName - * @param dropdownType - * @param expectedValue - */ -const checkDropdownField = (streamName: string, dropdownType: Dropdown, expectedValue: string | string[]) => { - const button = getFieldDropdownButton(streamName, dropdownType); - const isButtonContainsExactValue = (value: string) => cy.get(button).contains(new RegExp(`^${value}$`)); - - return Array.isArray(expectedValue) - ? expectedValue.every((value) => isButtonContainsExactValue(value)) - : isButtonContainsExactValue(expectedValue); -}; - -/** - * Check selected value in cursor dropdown - * @param streamName - * @param expectedValue - */ -export const checkCursorField = (streamName: string, expectedValue: string) => - checkDropdownField(streamName, "cursor", expectedValue); - -/** - * Check selected value(s) in primary key dropdown - * @param streamName - * @param expectedValues - */ -export const checkPrimaryKey = (streamName: string, expectedValues: string[]) => - checkDropdownField(streamName, "primaryKey", expectedValues); - -export const checkPreFilledPrimaryKeyField = (streamName: string, expectedValue: string) => { - cy.get(getPreFilledPrimaryKeyText(streamName)).contains(expectedValue); -}; - -export const isPrimaryKeyNonExist = (streamName: string) => { - cy.get(getPreFilledPrimaryKeyText(streamName)).should("not.exist"); -}; - -export const searchStream = (value: string) => { - cy.get(streamNameInput).type(value); -}; - -export const clearStreamSearch = () => { - cy.get(streamNameInput).clear(); -}; - -export const clickSaveReplication = ({ reset = false, confirm = true } = {}) => { - cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); - - submitButtonClick(); - - if (confirm) { - confirmStreamConfigurationChangedPopup({ reset }); - } - - cy.wait("@updateConnection").then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); -}; - -export const checkSuccessResult = () => { - cy.get(successResult).should("exist"); -}; - -export const confirmStreamConfigurationChangedPopup = ({ reset = false } = {}) => { - if (!reset) { - cy.get(resetModalResetCheckbox).click({ force: true }); - } - cy.get(saveStreamChangesButton).click(); -}; - -export const toggleStreamEnabledState = (streamName: string) => { - cy.get(streamSyncEnabledSwitch(streamName)).check({ force: true }); -}; - -export const checkSchemaChangesDetected = ({ breaking }: { breaking: boolean }) => { - cy.get(schemaChangesDetectedBanner).should("exist"); - cy.get(schemaChangesDetectedBanner) - .invoke("attr", "class") - .should("match", breaking ? /\_breaking/ : /nonBreaking/); - cy.get(schemaChangesBackdrop).should(breaking ? "exist" : "not.exist"); -}; - -export const checkSchemaChangesDetectedCleared = () => { - cy.get(schemaChangesDetectedBanner).should("not.exist"); - cy.get(schemaChangesBackdrop).should("not.exist"); -}; - -export const clickSchemaChangesReviewButton = () => { - cy.get(schemaChangesReviewButton).click(); - cy.get(schemaChangesReviewButton).should("be.disabled"); -}; - -export const selectNonBreakingChangesPreference = (preference: "ignore" | "disable") => { - cy.get(nonBreakingChangesPreference).click(); - cy.get(nonBreakingChangesPreferenceValue(preference)).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/settingsConnectionPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/settingsConnectionPage.ts deleted file mode 100644 index 5c4b1c00d5687..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/settingsConnectionPage.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { clickOnCellInTable } from "commands/common"; - -const settingsTab = "div[data-id='settings-step']"; -const sourceColumnName = "Source name"; -const destinationColumnName = "Destination name"; -const connectionsTable = "table[data-testid='connectionsTable']"; - -export const openConnectionOverviewBySourceName = (sourceName: string) => { - clickOnCellInTable(connectionsTable, sourceColumnName, sourceName); -}; - -export const openConnectionOverviewByDestinationName = (destinationName: string) => { - clickOnCellInTable(connectionsTable, destinationColumnName, destinationName); -}; - -export const goToSettingsPage = () => { - cy.get(settingsTab).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/sidebar.ts b/airbyte-webapp-e2e-tests/cypress/pages/sidebar.ts deleted file mode 100644 index c19b45ef907d6..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/sidebar.ts +++ /dev/null @@ -1,10 +0,0 @@ -const setting = "nav a[href*='settings']"; -const homepage = "[aria-label='Homepage']"; - -export const openSettings = () => { - cy.get(setting).click(); -}; - -export const openHomepage = () => { - cy.get(homepage).click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/sourcePage.ts b/airbyte-webapp-e2e-tests/cypress/pages/sourcePage.ts deleted file mode 100644 index ed80ecebb866e..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/sourcePage.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { clickOnCellInTable } from "commands/common"; - -const newSource = "button[data-id='new-source']"; -const sourcesTable = "table[data-testid='sourcesTable']"; -const sourceNameColumn = "Name"; - -export const goToSourcePage = () => { - cy.intercept("/api/v1/sources/list").as("getSourcesList"); - cy.visit("/source"); - cy.wait(3000); -}; - -export const openSourceDestinationFromGrid = (value: string) => { - cy.get("div").contains(value).click(); -}; - -export const openSourceOverview = (sourceName: string) => { - clickOnCellInTable(sourcesTable, sourceNameColumn, sourceName); -}; - -export const openNewSourceForm = () => { - cy.wait("@getSourcesList").then(({ response }) => { - if (response?.body.sources.length) { - cy.get(newSource).click(); - } - }); - cy.url().should("include", `/source/new-source`); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/plugins/index.ts b/airbyte-webapp-e2e-tests/cypress/plugins/index.ts deleted file mode 100644 index e13e5aa5f1c5a..0000000000000 --- a/airbyte-webapp-e2e-tests/cypress/plugins/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -/// -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -import Cypress from "cypress"; - -const pgp = require("pg-promise")(); -const cypressConfig = require(require("path").resolve("cypress.json")); - -interface dbConfig { - user: string; - host: string; - database: string; - password: string; - port: number; -} - -function dbConnection(query: any, userDefineConnection: dbConfig) { - let connection = cypressConfig.db; - if (userDefineConnection !== undefined) { - connection = userDefineConnection; - } - const db = pgp(connection); - return db.any(query).finally(db.$pool.end); -} - -/** - * @type {Cypress.PluginConfig} - */ -module.exports = (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - on("task", { - dbQuery: (query) => dbConnection(query.query, query.connection), - }); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/support/index.js b/airbyte-webapp-e2e-tests/cypress/support/index.js deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/airbyte-webapp-e2e-tests/dummy_api.js b/airbyte-webapp-e2e-tests/dummy_api.js deleted file mode 100644 index 83a878b2f75f8..0000000000000 --- a/airbyte-webapp-e2e-tests/dummy_api.js +++ /dev/null @@ -1,28 +0,0 @@ -// Script starting a basic webserver returning mocked data over an authenticated API to test the connector builder UI and connector builder server in an -// end to end fashion. - -// Start with `npm run createdummyapi` - -const http = require('http'); - -const items = [{ name: "abc" }, { name: "def" }, { name: "xxx" }, { name: "yyy" }]; - -const requestListener = function (req, res) { - if (req.headers["authorization"] !== "Bearer theauthkey") { - res.writeHead(403); res.end(JSON.stringify({ error: "Bad credentials" })); return; - } - if (req.url !== "/items") { - res.writeHead(404); res.end(JSON.stringify({ error: "Not found" })); return; - } - // Add more dummy logic in here - res.setHeader("Content-Type", "application/json"); - res.writeHead(200); - res.end(JSON.stringify({ items: [...items].splice(req.headers["offset"] ? Number(req.headers["offset"]) : 0, 2) })); -} - -const server = http.createServer(requestListener); -server.listen(6767); - -process.on('SIGINT', function () { - process.exit() -}) diff --git a/airbyte-webapp-e2e-tests/package-lock.json b/airbyte-webapp-e2e-tests/package-lock.json deleted file mode 100644 index 63caf3c6dc480..0000000000000 --- a/airbyte-webapp-e2e-tests/package-lock.json +++ /dev/null @@ -1,5732 +0,0 @@ -{ - "name": "airbyte-webapp-e2e-tests", - "version": "0.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "airbyte-webapp-e2e-tests", - "version": "0.0.0", - "devDependencies": { - "@types/node": "^18.11.9", - "@typescript-eslint/eslint-plugin": "^5.27.1", - "@typescript-eslint/parser": "^5.27.1", - "cypress": "^9.2.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-prettier": "^4.0.0", - "pg-promise": "^10.15.4", - "prettier": "^2.6.2", - "typescript": "^4.5.4" - }, - "engines": { - "node": "16.18.1" - } - }, - "node_modules/@cypress/request": { - "version": "2.88.10", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", - "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", - "dev": true, - "peer": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", - "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", - "dev": true, - "peer": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true, - "peer": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", - "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", - "dev": true - }, - "node_modules/@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.1.tgz", - "integrity": "sha512-cOizjPlKEh0bXdFrBLTrI/J6B/QMlhwE9auOov53tgB+qMukH6/h8YAK/qw+QJGct/PTbdh2lytGyipxCcEtAw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.45.1", - "@typescript-eslint/type-utils": "5.45.1", - "@typescript-eslint/utils": "5.45.1", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", - "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.1.tgz", - "integrity": "sha512-JQ3Ep8bEOXu16q0ztsatp/iQfDCtvap7sp/DKo7DWltUquj5AfCOpX2zSzJ8YkAVnrQNqQ5R62PBz2UtrfmCkA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.45.1", - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/typescript-estree": "5.45.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.1.tgz", - "integrity": "sha512-D6fCileR6Iai7E35Eb4Kp+k0iW7F1wxXYrOhX/3dywsOJpJAQ20Fwgcf+P/TDtvQ7zcsWsrJaglaQWDhOMsspQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/visitor-keys": "5.45.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.45.1.tgz", - "integrity": "sha512-aosxFa+0CoYgYEl3aptLe1svP910DJq68nwEJzyQcrtRhC4BN0tJAvZGAe+D0tzjJmFXe+h4leSsiZhwBa2vrA==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.45.1", - "@typescript-eslint/utils": "5.45.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.1.tgz", - "integrity": "sha512-HEW3U0E5dLjUT+nk7b4lLbOherS1U4ap+b9pfu2oGsW3oPu7genRaY9dDv3nMczC1rbnRY2W/D7SN05wYoGImg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.1.tgz", - "integrity": "sha512-76NZpmpCzWVrrb0XmYEpbwOz/FENBi+5W7ipVXAsG3OoFrQKJMiaqsBMbvGRyLtPotGqUfcY7Ur8j0dksDJDng==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/visitor-keys": "5.45.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.45.1.tgz", - "integrity": "sha512-rlbC5VZz68+yjAzQBc4I7KDYVzWG2X/OrqoZrMahYq3u8FFtmQYc+9rovo/7wlJH5kugJ+jQXV5pJMnofGmPRw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.45.1", - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/typescript-estree": "5.45.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.1.tgz", - "integrity": "sha512-cy9ln+6rmthYWjH9fmx+5FU/JDpjQb586++x2FZlveq7GdGuLLW9a2Jcst2TGekH82bXpfmRNSwP9tyEs6RjvQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.45.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "dev": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peer": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "peer": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-options": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.0.tgz", - "integrity": "sha512-qSELrEaEz4sGwTs4Qh+swQkjiHAysC4rot21+jzXU86dJzNG+FDqBzyS3ohSoTRf4ZLA3FSwxQdiuNl5NXUtvA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ci-info": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", - "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", - "dev": true - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz", - "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "colors": "^1.1.2" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cypress": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-9.2.0.tgz", - "integrity": "sha512-Jn26Tprhfzh/a66Sdj9SoaYlnNX6Mjfmj5PHu2a7l3YHXhrgmavM368wjCmgrxC6KHTOv9SpMQGhAJn+upDViA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@cypress/request": "^2.88.10", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", - "@types/sinonjs__fake-timers": "^6.0.2", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "3.7.2", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.0", - "commander": "^5.1.0", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "eventemitter2": "^6.4.3", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.5", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "url": "^0.11.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/cypress/node_modules/@types/node": { - "version": "14.18.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz", - "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==", - "dev": true - }, - "node_modules/cypress/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dayjs": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz", - "integrity": "sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "peer": true - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz", - "integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==", - "dev": true, - "peer": true, - "dependencies": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-cypress": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz", - "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==", - "dev": true, - "dependencies": { - "globals": "^11.12.0" - }, - "peerDependencies": { - "eslint": ">= 3.2.1" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", - "dev": true, - "peer": true, - "dependencies": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "peer": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter2": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.3.tgz", - "integrity": "sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ==", - "dev": true - }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "peer": true - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "peer": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true, - "peer": true - }, - "node_modules/fastq": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", - "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "peer": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "peer": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", - "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", - "dev": true, - "peer": true - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true, - "peer": true - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "dependencies": { - "async": "^3.2.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "peer": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/ignore": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", - "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "peer": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true, - "peer": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", - "dev": true, - "engines": { - "node": "> 0.8" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/listr2": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.5.tgz", - "integrity": "sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.4.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "peer": true - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true, - "peer": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "peer": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", - "dev": true - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", - "dev": true - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "peer": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/pg": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz", - "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==", - "dev": true, - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.2", - "pg-protocol": "^1.5.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "pg-native": ">=3.0.1" - }, - "peerDependenciesMeta": { - "pg-native": { - "optional": true - } - } - }, - "node_modules/pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==", - "dev": true - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-minify": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz", - "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==", - "dev": true, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/pg-pool": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz", - "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==", - "dev": true, - "peerDependencies": { - "pg": ">=8.0" - } - }, - "node_modules/pg-promise": { - "version": "10.15.4", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.15.4.tgz", - "integrity": "sha512-BKlHCMCdNUmF6gagVbehRWSEiVcZzPVltEx14OJExR9Iz9/1R6KETDWLLGv2l6yRqYFnEZZy1VDjRhArzeIGrw==", - "dev": true, - "dependencies": { - "assert-options": "0.8.0", - "pg": "8.8.0", - "pg-minify": "1.6.2", - "spex": "3.2.0" - }, - "engines": { - "node": ">=12.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", - "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==", - "dev": true - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dev": true, - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dev": true, - "dependencies": { - "split2": "^4.1.0" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true, - "dependencies": { - "throttleit": "^1.0.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", - "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", - "dev": true, - "dependencies": { - "tslib": "~2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz", - "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==", - "dev": true, - "engines": { - "node": ">=4.5" - } - }, - "node_modules/split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", - "dev": true, - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true, - "peer": true - }, - "node_modules/throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "peer": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", - "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "peer": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true, - "peer": true - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - }, - "dependencies": { - "@cypress/request": { - "version": "2.88.10", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz", - "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - } - }, - "@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", - "dev": true, - "peer": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "peer": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "peer": true - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", - "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", - "dev": true, - "peer": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true, - "peer": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", - "dev": true - }, - "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", - "dev": true - }, - "@types/sizzle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", - "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", - "dev": true - }, - "@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.1.tgz", - "integrity": "sha512-cOizjPlKEh0bXdFrBLTrI/J6B/QMlhwE9auOov53tgB+qMukH6/h8YAK/qw+QJGct/PTbdh2lytGyipxCcEtAw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.45.1", - "@typescript-eslint/type-utils": "5.45.1", - "@typescript-eslint/utils": "5.45.1", - "debug": "^4.3.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "dependencies": { - "ignore": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", - "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", - "dev": true - } - } - }, - "@typescript-eslint/parser": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.1.tgz", - "integrity": "sha512-JQ3Ep8bEOXu16q0ztsatp/iQfDCtvap7sp/DKo7DWltUquj5AfCOpX2zSzJ8YkAVnrQNqQ5R62PBz2UtrfmCkA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.45.1", - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/typescript-estree": "5.45.1", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.1.tgz", - "integrity": "sha512-D6fCileR6Iai7E35Eb4Kp+k0iW7F1wxXYrOhX/3dywsOJpJAQ20Fwgcf+P/TDtvQ7zcsWsrJaglaQWDhOMsspQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/visitor-keys": "5.45.1" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.45.1.tgz", - "integrity": "sha512-aosxFa+0CoYgYEl3aptLe1svP910DJq68nwEJzyQcrtRhC4BN0tJAvZGAe+D0tzjJmFXe+h4leSsiZhwBa2vrA==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.45.1", - "@typescript-eslint/utils": "5.45.1", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.1.tgz", - "integrity": "sha512-HEW3U0E5dLjUT+nk7b4lLbOherS1U4ap+b9pfu2oGsW3oPu7genRaY9dDv3nMczC1rbnRY2W/D7SN05wYoGImg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.1.tgz", - "integrity": "sha512-76NZpmpCzWVrrb0XmYEpbwOz/FENBi+5W7ipVXAsG3OoFrQKJMiaqsBMbvGRyLtPotGqUfcY7Ur8j0dksDJDng==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/visitor-keys": "5.45.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.45.1.tgz", - "integrity": "sha512-rlbC5VZz68+yjAzQBc4I7KDYVzWG2X/OrqoZrMahYq3u8FFtmQYc+9rovo/7wlJH5kugJ+jQXV5pJMnofGmPRw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.45.1", - "@typescript-eslint/types": "5.45.1", - "@typescript-eslint/typescript-estree": "5.45.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "dependencies": { - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.45.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.1.tgz", - "integrity": "sha512-cy9ln+6rmthYWjH9fmx+5FU/JDpjQb586++x2FZlveq7GdGuLLW9a2Jcst2TGekH82bXpfmRNSwP9tyEs6RjvQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.45.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "dev": true, - "peer": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peer": true, - "requires": {} - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "peer": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-options": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.0.tgz", - "integrity": "sha512-qSELrEaEz4sGwTs4Qh+swQkjiHAysC4rot21+jzXU86dJzNG+FDqBzyS3ohSoTRf4ZLA3FSwxQdiuNl5NXUtvA==", - "dev": true - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "dev": true - }, - "cachedir": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", - "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", - "dev": true - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "peer": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", - "dev": true - }, - "ci-info": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", - "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-table3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.0.tgz", - "integrity": "sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ==", - "dev": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^4.2.0" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "optional": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true - }, - "common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cypress": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-9.2.0.tgz", - "integrity": "sha512-Jn26Tprhfzh/a66Sdj9SoaYlnNX6Mjfmj5PHu2a7l3YHXhrgmavM368wjCmgrxC6KHTOv9SpMQGhAJn+upDViA==", - "dev": true, - "requires": { - "@cypress/request": "^2.88.10", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^14.14.31", - "@types/sinonjs__fake-timers": "^6.0.2", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "3.7.2", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.0", - "commander": "^5.1.0", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "eventemitter2": "^6.4.3", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.5", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "url": "^0.11.0", - "yauzl": "^2.10.0" - }, - "dependencies": { - "@types/node": { - "version": "14.18.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.33.tgz", - "integrity": "sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dayjs": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz", - "integrity": "sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "peer": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "peer": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "peer": true - }, - "eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.5.0.tgz", - "integrity": "sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==", - "dev": true, - "peer": true, - "requires": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "peer": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "peer": true - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-plugin-cypress": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz", - "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==", - "dev": true, - "requires": { - "globals": "^11.12.0" - } - }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "peer": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", - "dev": true, - "peer": true, - "requires": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "peer": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "peer": true - }, - "eventemitter2": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.3.tgz", - "integrity": "sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ==", - "dev": true - }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "requires": { - "pify": "^2.2.0" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "peer": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "peer": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true, - "peer": true - }, - "fastq": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", - "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "peer": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "peer": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz", - "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==", - "dev": true, - "peer": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true, - "peer": true - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "requires": { - "async": "^3.2.0" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "peer": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "global-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", - "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", - "dev": true, - "requires": { - "ini": "2.0.0" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "dependencies": { - "ignore": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", - "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", - "dev": true - } - } - }, - "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - } - }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "peer": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "peer": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "peer": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true - }, - "is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "requires": { - "ci-info": "^3.2.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "requires": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "peer": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "peer": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true, - "peer": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "peer": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "listr2": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.5.tgz", - "integrity": "sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.4.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "peer": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", - "dev": true - }, - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "requires": { - "chalk": "^4.0.0" - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dev": true, - "requires": { - "mime-db": "1.51.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true, - "peer": true - }, - "natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "peer": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=", - "dev": true - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "peer": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pg": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz", - "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==", - "dev": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.2", - "pg-protocol": "^1.5.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==", - "dev": true - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "dev": true - }, - "pg-minify": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz", - "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==", - "dev": true - }, - "pg-pool": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz", - "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==", - "dev": true, - "requires": {} - }, - "pg-promise": { - "version": "10.15.4", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.15.4.tgz", - "integrity": "sha512-BKlHCMCdNUmF6gagVbehRWSEiVcZzPVltEx14OJExR9Iz9/1R6KETDWLLGv2l6yRqYFnEZZy1VDjRhArzeIGrw==", - "dev": true, - "requires": { - "assert-options": "0.8.0", - "pg": "8.8.0", - "pg-minify": "1.6.2", - "spex": "3.2.0" - } - }, - "pg-protocol": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", - "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==", - "dev": true - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dev": true, - "requires": { - "split2": "^4.1.0" - } - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "dev": true - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "dev": true - }, - "postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "dev": true - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dev": true, - "requires": { - "xtend": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "peer": true - }, - "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "peer": true - }, - "proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", - "dev": true, - "requires": { - "throttleit": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "peer": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", - "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", - "dev": true, - "requires": { - "tslib": "~2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "spex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz", - "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==", - "dev": true - }, - "split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "peer": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true, - "peer": true - }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "peer": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "typescript": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", - "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "peer": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true, - "peer": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "peer": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/airbyte-webapp-e2e-tests/package.json b/airbyte-webapp-e2e-tests/package.json deleted file mode 100644 index c7d07699e8597..0000000000000 --- a/airbyte-webapp-e2e-tests/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "airbyte-webapp-e2e-tests", - "version": "0.0.0", - "description": "Airbyte e2e testing", - "engines": { - "node": "16.18.1" - }, - "scripts": { - "cypress:open": "cypress open", - "cypress:ci": "CYPRESS_BASE_URL=http://localhost:8000 cypress run", - "cypress:ci:record": "CYPRESS_BASE_URL=http://localhost:8000 cypress run --record --key $CYPRESS_KEY", - "createdbsource": "docker run --rm -d -p 5433:5432 -e POSTGRES_PASSWORD=secret_password -e POSTGRES_DB=airbyte_ci_source --name airbyte_ci_pg_source postgres", - "createdbdestination": "docker run --rm -d -p 5434:5432 -e POSTGRES_PASSWORD=secret_password -e POSTGRES_DB=airbyte_ci_destination --name airbyte_ci_pg_destination postgres", - "createdummyapi": "docker run --rm -d -p 6767:6767 --network=airbyte_airbyte_internal --mount type=bind,source=\"$(pwd)\"/dummy_api.js,target=/index.js --name=dummy_api node:16-alpine \"index.js\"", - "lint": "eslint --ext js,ts,tsx cypress" - }, - "devDependencies": { - "@types/node": "^18.11.9", - "@typescript-eslint/eslint-plugin": "^5.27.1", - "@typescript-eslint/parser": "^5.27.1", - "cypress": "^9.2.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-prettier": "^4.0.0", - "pg-promise": "^10.15.4", - "prettier": "^2.6.2", - "typescript": "^4.5.4" - } -} diff --git a/airbyte-webapp-e2e-tests/tsconfig.json b/airbyte-webapp-e2e-tests/tsconfig.json deleted file mode 100644 index 43def3592a3f2..0000000000000 --- a/airbyte-webapp-e2e-tests/tsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "include": ["./**/*.ts"], - "exclude": [], - "compilerOptions": { - "baseUrl": "cypress", - "target": "es5", - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "jsx": "react-jsx", - "noFallthroughCasesInSwitch": true, - "types": ["cypress", "node"], - "lib": ["es2015", "dom"], - "isolatedModules": false, - "allowJs": true, - "noEmit": true, - "paths": { - "commands/*": ["commands/*"], - "fixtures/*": ["fixtures/*"], - "integration": ["integration/*"], - "pages/*": ["pages/*"], - "plugins/*": ["plugins/*"] - } - } -} diff --git a/airbyte-webapp/.env b/airbyte-webapp/.env deleted file mode 100644 index df37c64423e81..0000000000000 --- a/airbyte-webapp/.env +++ /dev/null @@ -1,6 +0,0 @@ -REACT_APP_SEGMENT_TOKEN=6cxNSmQyGSKcATLdJ2pL6WsawkzEMDAN -REACT_APP_FULL_STORY_ORG=13AXQ4 -REACT_APP_SENTRY_DSN= -REACT_APP_INTERCOM_APP_ID=nj1oam7s -REACT_APP_OSANO=16A0CTTE7vE8m1Qif/67beec9b-e563-4736-bdb4-4fe4adc39d48 -REACT_APP_CLOUD_PUBLIC_API_URL=/cloud_api diff --git a/airbyte-webapp/.eslintrc.js b/airbyte-webapp/.eslintrc.js deleted file mode 100644 index 28aba8e623a25..0000000000000 --- a/airbyte-webapp/.eslintrc.js +++ /dev/null @@ -1,129 +0,0 @@ -module.exports = { - extends: [ - "react-app", - "plugin:@typescript-eslint/recommended", - "plugin:jest/recommended", - "prettier", - "plugin:prettier/recommended", - "plugin:css-modules/recommended", - "plugin:jsx-a11y/recommended", - "plugin:@airbyte/recommended", - ], - plugins: ["@typescript-eslint", "prettier", "unused-imports", "css-modules", "jsx-a11y", "@airbyte"], - parserOptions: { - ecmaVersion: 2020, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, - }, - rules: { - "jsx-a11y/label-has-associated-control": "error", - curly: "warn", - "css-modules/no-undef-class": "off", - "css-modules/no-unused-class": ["error", { camelCase: true }], - "dot-location": "warn", - "dot-notation": "warn", - eqeqeq: "error", - "prettier/prettier": "warn", - "unused-imports/no-unused-imports": "warn", - "no-else-return": "warn", - "no-lonely-if": "warn", - "no-inner-declarations": "off", - "no-unused-vars": "off", - "no-useless-computed-key": "warn", - "no-useless-return": "warn", - "no-var": "warn", - "object-shorthand": ["warn", "always"], - "prefer-arrow-callback": "warn", - "prefer-const": "warn", - "prefer-destructuring": ["warn", { AssignmentExpression: { array: true } }], - "prefer-object-spread": "warn", - "prefer-template": "warn", - "spaced-comment": ["warn", "always", { markers: ["/"] }], - yoda: "warn", - "import/order": [ - "warn", - { - "newlines-between": "always", - groups: ["type", "builtin", "external", "internal", ["parent", "sibling"], "index"], - pathGroupsExcludedImportTypes: ["builtin"], - pathGroups: [ - { - pattern: "components{/**,}", - group: "internal", - }, - { - pattern: "+(config|core|hooks|locales|packages|pages|services|types|utils|views){/**,}", - group: "internal", - position: "after", - }, - ], - alphabetize: { - order: "asc" /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */, - caseInsensitive: true /* ignore case. Options: [true, false] */, - }, - }, - ], - "@typescript-eslint/array-type": ["warn", { default: "array-simple" }], - "@typescript-eslint/ban-ts-comment": [ - "warn", - { - "ts-expect-error": "allow-with-description", - }, - ], - "@typescript-eslint/ban-types": "warn", - "@typescript-eslint/consistent-indexed-object-style": ["warn", "record"], - "@typescript-eslint/consistent-type-definitions": ["warn", "interface"], - "@typescript-eslint/no-unused-vars": "warn", - "react/function-component-definition": [ - "warn", - { - namedComponents: "arrow-function", - unnamedComponents: "arrow-function", - }, - ], - "jest/consistent-test-it": ["warn", { fn: "it", withinDescribe: "it" }], - "react/no-danger": "error", - "react/jsx-boolean-value": "warn", - "react/jsx-curly-brace-presence": "warn", - "react/jsx-fragments": "warn", - "react/jsx-no-useless-fragment": ["warn", { allowExpressions: true }], - "react/self-closing-comp": "warn", - "react/style-prop-object": ["warn", { allow: ["FormattedNumber"] }], - "no-restricted-imports": [ - "error", - { - paths: [ - { - name: "lodash", - message: 'Please use `import [function] from "lodash/[function]";` instead.', - }, - ], - patterns: ["!lodash/*"], - }, - ], - }, - parser: "@typescript-eslint/parser", - overrides: [ - { - files: ["scripts/**/*", "packages/**/*"], - rules: { - "@typescript-eslint/no-var-requires": "off", - }, - }, - { - // Only applies to files in src. Rules should be in here that are requiring type information - // and thus require the below parserOptions. - files: ["src/**/*"], - parserOptions: { - tsconfigRootDir: __dirname, - project: "./tsconfig.json", - }, - rules: { - "@typescript-eslint/await-thenable": "warn", - "@typescript-eslint/no-unnecessary-type-assertion": "warn", - }, - }, - ], -}; diff --git a/airbyte-webapp/.gitattributes b/airbyte-webapp/.gitattributes deleted file mode 100644 index f00342d0d17ee..0000000000000 --- a/airbyte-webapp/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -/public/fonts/**/*.svg binary diff --git a/airbyte-webapp/.gitignore b/airbyte-webapp/.gitignore deleted file mode 100644 index 10ee29f524a01..0000000000000 --- a/airbyte-webapp/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store - -# Log files -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -*.iml -/.idea - -# Environment overwrites -.env.development -.env.production -.env.local -.env.development.local -.env.test.local -.env.production.local - -# Local overwrites -.experiments.json - -storybook-static/ - -# Generated by our build-info plugin -/public/buildInfo.json - -# Ignore generated API clients, since they're automatically generated -/src/core/request/AirbyteClient.ts -/src/core/request/ConnectorBuilderClient.ts -/src/core/request/ConnectorManifest.ts diff --git a/airbyte-webapp/.husky/pre-commit b/airbyte-webapp/.husky/pre-commit deleted file mode 100755 index 4e96aec869c23..0000000000000 --- a/airbyte-webapp/.husky/pre-commit +++ /dev/null @@ -1,10 +0,0 @@ -# Only run this pre-commit hook when npx is actually in the path. -# Since CI will fail on misformated frontend code we consider this hook optional -# and don't want to fail if the system doesn't have the requirements to run it. -if command -v npx &> /dev/null; then - # Only run if `npx` is at least version 8, since earlier versions didn't support the --no flag - npxMajorVersion=$(npx --version | cut -d. -f1) - if [ "$npxMajorVersion" -ge "8" ]; then - cd airbyte-webapp && npx --no lint-staged - fi -fi \ No newline at end of file diff --git a/airbyte-webapp/.npmrc b/airbyte-webapp/.npmrc deleted file mode 100644 index 618365b27463c..0000000000000 --- a/airbyte-webapp/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -engine-strict=true -enable-pre-post-scripts=true diff --git a/airbyte-webapp/.nvmrc b/airbyte-webapp/.nvmrc deleted file mode 100644 index a2d511aff36c3..0000000000000 --- a/airbyte-webapp/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -16.18.1 \ No newline at end of file diff --git a/airbyte-webapp/.prettierrc.js b/airbyte-webapp/.prettierrc.js deleted file mode 100644 index c59c9621a4250..0000000000000 --- a/airbyte-webapp/.prettierrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - printWidth: 120, - endOfLine: "lf", -}; diff --git a/airbyte-webapp/.storybook/logo.png b/airbyte-webapp/.storybook/logo.png deleted file mode 100644 index 8b38e50dec15bf26ac03676cc92cf9798e12caf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4866 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 Pe|cc4Iw}=PHsSvRZ}zM0 diff --git a/airbyte-webapp/.storybook/main.ts b/airbyte-webapp/.storybook/main.ts deleted file mode 100644 index 3712b33bf91c7..0000000000000 --- a/airbyte-webapp/.storybook/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { StorybookConfig } from "@storybook/react-vite"; - -const config: StorybookConfig = { - framework: "@storybook/react-vite", - stories: ["../src/**/*.stories.@(ts|tsx)"], - addons: [ - "@storybook/addon-links", - "@storybook/addon-essentials", - ], -}; - -export default config; diff --git a/airbyte-webapp/.storybook/manager.ts b/airbyte-webapp/.storybook/manager.ts deleted file mode 100644 index 4df6810176526..0000000000000 --- a/airbyte-webapp/.storybook/manager.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { addons } from "@storybook/addons"; -import theme from "./theme"; - -addons.setConfig({ - panelPosition: "bottom", - theme -}); \ No newline at end of file diff --git a/airbyte-webapp/.storybook/preview.ts b/airbyte-webapp/.storybook/preview.ts deleted file mode 100644 index 1e86bf0d54bfd..0000000000000 --- a/airbyte-webapp/.storybook/preview.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { withProviders } from "./withProvider"; - -import "../public/index.css"; -import "../src/scss/global.scss"; -import "../src/dayjs-setup"; - -export const parameters = {}; -export const decorators = [withProviders]; diff --git a/airbyte-webapp/.storybook/theme.tsx b/airbyte-webapp/.storybook/theme.tsx deleted file mode 100644 index c48a915061259..0000000000000 --- a/airbyte-webapp/.storybook/theme.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { create } from "@storybook/theming/create"; -import Image from "./logo.png"; - -export default create({ - brandTitle: "Airbyte", - brandUrl: "https://airbyte.com", - brandImage: Image, -}); diff --git a/airbyte-webapp/.storybook/withProvider.tsx b/airbyte-webapp/.storybook/withProvider.tsx deleted file mode 100644 index fd2f316c40901..0000000000000 --- a/airbyte-webapp/.storybook/withProvider.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from "react"; - -import { MemoryRouter } from "react-router-dom"; -import { IntlProvider } from "react-intl"; -import { ThemeProvider } from "styled-components"; -import { QueryClientProvider, QueryClient } from "react-query"; - -// TODO: theme was not working correctly so imported directly -import { theme } from "../src/theme"; -import messages from "../src/locales/en.json"; -import { FeatureService } from "../src/hooks/services/Feature"; -import { ConfigServiceProvider, config } from "../src/config"; -import { DocumentationPanelProvider } from "../src/views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext"; -import { ServicesProvider } from "../src/core/servicesProvider"; -import { analyticsServiceContext } from "../src/hooks/services/Analytics"; -import { AppMonitoringServiceProvider } from "../src/hooks/services/AppMonitoringService"; -import type { AnalyticsService } from "../src/core/analytics"; - -const analyticsContextMock: AnalyticsService = { - track: () => {}, - setContext: () => {}, - removeFromContext: () => {}, -} as unknown as AnalyticsService; - -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: false, - suspense: true, - }, - }, -}); - -export const withProviders = (getStory) => ( - - - - - - - - - - - - {getStory()} - - - - - - - - - - - -); diff --git a/airbyte-webapp/.stylelintignore b/airbyte-webapp/.stylelintignore deleted file mode 100644 index 806b6a32b8e99..0000000000000 --- a/airbyte-webapp/.stylelintignore +++ /dev/null @@ -1 +0,0 @@ -coverage/**/* diff --git a/airbyte-webapp/.stylelintrc b/airbyte-webapp/.stylelintrc deleted file mode 100644 index e777d222acd55..0000000000000 --- a/airbyte-webapp/.stylelintrc +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": [ - "stylelint-config-standard", - "stylelint-config-standard-scss", - "stylelint-config-css-modules", - "stylelint-config-prettier-scss" - ], - "rules": { - "selector-class-pattern": "^[a-z][a-zA-Z0-9]+$", - "color-function-notation": null, - "font-family-name-quotes": null, - "no-unknown-animations": true, - "custom-property-empty-line-before": null, - "scss/dollar-variable-empty-line-before": null, - "scss/dollar-variable-pattern": null, - "scss/percent-placeholder-pattern": null, - "value-keyword-case": null, - "color-no-hex": true, - "airbyte/no-color-variables-in-rgba": true, - "airbyte/no-use-renaming": true - }, - "ignoreFiles": ["**/build/**", "**/dist/**"], - "plugins": ["./packages/stylelint-plugin/index.js"] -} diff --git a/airbyte-webapp/Dockerfile b/airbyte-webapp/Dockerfile deleted file mode 100644 index 4e90bb10c5cd5..0000000000000 --- a/airbyte-webapp/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -ARG NGINX_IMAGE=nginx:alpine -FROM ${NGINX_IMAGE} as webapp - -EXPOSE 80 - -COPY bin/build /usr/share/nginx/html -COPY bin/nginx/default.conf.template /etc/nginx/templates/default.conf.template diff --git a/airbyte-webapp/README.md b/airbyte-webapp/README.md deleted file mode 100644 index 3feefee4c40ac..0000000000000 --- a/airbyte-webapp/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# airbyte-webapp - -This module contains the Airbyte Webapp. It is a React app written in TypeScript. -The webapp compiles to static HTML, JavaScript and CSS, which is served (in OSS) via -a nginx in the airbyte-webapp docker image. This nginx also serves as the reverse proxy -for accessing the server APIs in other images. - -## Building the webapp - -You can build the webapp using Gradle in the root of the repository: - -```sh -# Only compile and build the docker webapp image: -SUB_BUILD=PLATFORM ./gradlew :airbyte-webapp:assemble -# Build the webapp and additional artifacts and run tests: -SUB_BUILD=PLATFORM ./gradlew :airbyte-webapp:build -``` - -## Developing the webapp - -For an instruction how to develop on the webapp, please refer to our [documentation](https://docs.airbyte.com/contributing-to-airbyte/developing-locally/#develop-on-airbyte-webapp). - -### Entrypoints - -* `airbyte-webapp/src/App.tsx` is the entrypoint into the OSS version of the webapp. -* `airbyte-webapp/src/packages/cloud/App.tsx` is the entrypoint into the Cloud version of the webapp. diff --git a/airbyte-webapp/STYLEGUIDE.md b/airbyte-webapp/STYLEGUIDE.md deleted file mode 100644 index 6c1e65e50f772..0000000000000 --- a/airbyte-webapp/STYLEGUIDE.md +++ /dev/null @@ -1,72 +0,0 @@ -# Frontend Style Guide - -This serves as a living document regarding conventions we have agreed upon as a frontend team. In general, the aim of these decisions and discussions is to both (a) increase the readability and consistency of our code and (b) decrease day to day decision-making so we can spend more time writing better code. - -## General Code Style and Formatting - -- Where possible, we rely on automated systems to maintain consistency in code style -- We use eslint, Prettier, and VSCode settings to automate these choices. The configuration files for these are checked into our repository, so no individual setup should be required beyond ensuring your VSCode settings include: - -``` -"editor.codeActionsOnSave": { - "source.fixAll.eslint": true, -} -``` - -- Don’t use single-character names. Using meaningful name for function parameters is a way of making the code self-documented and we always should do it. Example: - - .filter(([key, value]) => isDefined(value.default) ✅ - - .filter(([k, v]) => isDefined(v.default) ❌ - -## Exporting - -- Export at declaration, not at the bottom. For example: - - export const myVar ✅ - - const myVar; export { myVar }; ❌ - -## Component Props - -- Use explicit, verbose naming - - ie: `interface ConnectionFormProps` not `interface iProps` - -## Testing - -- Test files should be store alongside the files/features they are testing -- Use the prop `data-testid` instead of `data-id` - -## Types - -- For component props, prefer type unions over enums: - - `type SomeType = “some” | “type”;` ✅ - - `enum SomeEnum = { SOME: “some”, TYPE: “type” };` ❌ - - Exceptions may include: - - Generated using enums from the API - - When the value on an enum is cleaner than the string - - In this case use `const enum` instead - -## Styling - -### Color variables cannot be used inside of rgba() functions - -Our SCSS color variables compile to `rgb(X, Y, Z)`, which is an invalid value in the CSS `rgba()` function. A custom stylelint rule, `airbyte/no-color-variables-in-rgba`, enforces this rule. - -❌ Incorrect - -```scss -@use "scss/colors"; - -.myClass { - background-color: rgba(colors.$blue-400, 50%); -} -``` - -✅ Correct - define a color variable with transparency and use it directly - -```scss -@use "scss/colors"; - -.myClass { - background-color: colors.$blue-transparent; -} -``` - -> Historical context: previously there was some usage of color variables inside `rgba()` functions. In these cases, _SASS_ was actually compiling this into CSS for us, because it knew to convert `rgba(rgb(255, 0, 0), 50%)` into `rgb(255, 0, 0, 50%)`. Now that we use CSS Custom Properties for colors, SASS cannot know the value of the color variable at build time. So it outputs `rgba(var(--blue), 50%)` which will not work as expected. diff --git a/airbyte-webapp/babel.config.js b/airbyte-webapp/babel.config.js deleted file mode 100644 index e867c8c8a46f4..0000000000000 --- a/airbyte-webapp/babel.config.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - env: { - test: { - // Define presets used to compile code when running jest tests - presets: [ - ["@babel/preset-env", { targets: { node: "current" } }], - ["@babel/preset-react", { runtime: "automatic" }], - "@babel/preset-typescript", - ], - }, - }, -}; diff --git a/airbyte-webapp/build.gradle b/airbyte-webapp/build.gradle deleted file mode 100644 index a052ea55ebbad..0000000000000 --- a/airbyte-webapp/build.gradle +++ /dev/null @@ -1,145 +0,0 @@ -plugins { - id "base" - id "com.github.node-gradle.node" version "3.4.0" -} - -// Use the node version that's defined in the .nvmrc file -def nodeVersion = new File("${projectDir}/.nvmrc").text.trim(); - -// Read pnpm version to use from package.json engines.pnpm entry -def pnpmVer = new groovy.json.JsonSlurper().parse(new File("${projectDir}/package.json")).engines.pnpm.trim(); - -// This array should contain a path to all configs that are common to most build tasks and -// might affect them (i.e. if any of those files change we want to rerun most tasks) -def commonConfigs = [ - '.env', - 'package.json', - 'pnpm-lock.yaml', - 'tsconfig.json', - '.prettierrc.js' -] - -node { - download = true - version = nodeVersion - pnpmVersion = pnpmVer -} - -task validateLockFiles { - description "Validate only a pnpm-lock.yaml lock file exists" - doLast { - assert file("pnpm-lock.yaml").exists() - assert !file("package-lock.json").exists() - assert !file("yarn.lock").exists() - } -} - -pnpmInstall.dependsOn validateLockFiles -// Make sure `pnpmInstall` always runs, since it's better at determining -// whether it's needs to do anything than Gradle can -pnpmInstall.outputs.upToDateWhen { false } - -task pnpmBuild(type: PnpmTask) { - dependsOn pnpmInstall - - args = ['build'] - - inputs.files commonConfigs - inputs.file '.eslintrc.js' - inputs.dir 'public' - inputs.dir 'src' - - outputs.dir 'build/app' -} - -task test(type: PnpmTask) { - dependsOn assemble - - args = ['run', 'test:ci'] - inputs.files commonConfigs - inputs.dir 'src' -} - -task licenseCheck(type: PnpmTask) { - dependsOn pnpmInstall - - args = ['run', 'license-check'] - inputs.files commonConfigs - inputs.file 'scripts/license-check.js' - - // The licenseCheck has no outputs, thus we always treat the outpus up to date - // as long as the inputs have not changed - outputs.upToDateWhen { true } -} - -task validateLinks(type: PnpmTask) { - dependsOn pnpmInstall - - args = ['run', 'validate-links'] - - // Since the output of this task depends on availability of URLs - // we never want to treat it as "up-to-date" and always want to run it - outputs.upToDateWhen { false } -} - -task buildStorybook(type: PnpmTask) { - dependsOn pnpmInstall - args = ['run', 'build:storybook'] - - inputs.files commonConfigs - inputs.dir '.storybook' - inputs.dir 'public' - inputs.dir 'src' - - outputs.dir 'build/storybook' - - environment = [ - 'NODE_OPTIONS': '--max_old_space_size=4096' - ] -} - -task copyBuildOutput(type: Copy) { - dependsOn copyDocker, pnpmBuild - - from "${project.projectDir}/build/app" - into 'build/docker/bin/build' -} - -task copyDocs(type: Copy) { - dependsOn copyDocker, copyBuildOutput - - from "${project.rootProject.projectDir}/docs/integrations" - into "build/docker/bin/build/docs/integrations" - // google-ads.md is blocked by Ad Blockers - rename ('google-ads.md', 'gglad.md') - duplicatesStrategy DuplicatesStrategy.INCLUDE -} - -// Copy images that are used in .md integration documentation docs -task copyDocAssets(type: Copy) { - dependsOn copyDocker, copyBuildOutput - - from "${project.rootProject.projectDir}/docs/.gitbook" - into "build/docker/bin/build/docs/.gitbook" - duplicatesStrategy DuplicatesStrategy.INCLUDE -} - -task copyNginx(type: Copy) { - dependsOn copyDocker - - from "${project.projectDir}/nginx" - into "build/docker/bin/nginx" -} - -// Those tasks should be run as part of the "check" task -check.dependsOn validateLinks, licenseCheck, test - -build.dependsOn buildStorybook - -tasks.named("buildDockerImage") { - dependsOn copyDocker - dependsOn copyBuildOutput - dependsOn copyNginx - dependsOn copyDocs - dependsOn copyDocAssets -} diff --git a/airbyte-webapp/docs/HowTo-ConnectionSpecification.md b/airbyte-webapp/docs/HowTo-ConnectionSpecification.md deleted file mode 100644 index f9b264cf2082b..0000000000000 --- a/airbyte-webapp/docs/HowTo-ConnectionSpecification.md +++ /dev/null @@ -1,35 +0,0 @@ -0. run `npm install` (make sure to install node 16 if you don't already have it) -1. run `npm run storybook` in `airbyte-webapp` directory -2. open `ServiceForm` component story http://localhost:9009/?path=/story/views-serviceform--source -3. press `raw` on the specifications property, so you will be able to past json in string format. -4. edit specifications property to the connectionConfigration you want - -e.g. -``` -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "BigQuery Destination Spec", - "type": "object", - "required": ["project_id", "dataset_id"], - "properties": { - "project_id": { - "type": "string", - "description": "The GCP project ID for the project containing the target BigQuery dataset.", - "title": "Project ID" - }, - "dataset_id": { - "type": "string", - "description": "Default BigQuery Dataset ID tables are replicated to if the source does not specify a namespace.", - "title": "Default Dataset ID" - }, - "credentials_json": { - "type": "string", - "description": "The contents of the JSON service account key. Check out the docs if you need help generating this key. Default credentials will be used if this field is left empty.", - "title": "Credentials JSON", - "airbyte_secret": true - } - } - } -``` - -![img.png](img.png) diff --git a/airbyte-webapp/docs/HowTo-EnvVariables.md b/airbyte-webapp/docs/HowTo-EnvVariables.md deleted file mode 100644 index a2edf83120f78..0000000000000 --- a/airbyte-webapp/docs/HowTo-EnvVariables.md +++ /dev/null @@ -1,28 +0,0 @@ -## Environment variables - -Currently we have 2 types of environment variables: - -1. Statically injected build time variables -2. Dynamic env variables injected via `window` - -### Static env variables - -The environment variables are embedded during the build time. Since our app is based on Create React App that produces a -static HTML/CSS/JS bundle, it can’t possibly read them at runtime. - -Static env variables name should always start with `REACT_APP_` - -### Dynamic env variables - -Dynamic env variables in our cases are injected into app by nginx - -```html - -; -``` - -later we can use any of the declared variables from window diff --git a/airbyte-webapp/docs/img.png b/airbyte-webapp/docs/img.png deleted file mode 100644 index 6bd0f60607a6dcdd3b727fded67ee87c45a93ab4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 173578 zcmd43XFS_)8$R6e(?M0MR7=sIwTdnjMXidqw%DXM5Tm0r2V`8}@dJkR4iE|KbA~rU5qW}1!;-R|=_~SpC?B9z*p1b_#*)-<^ zUH;Q6*RNI$d9EKPH(bo={(SmsoPHOo{2cu88utg0nt{+R-Kn>K`gA{naJm*vNsbh% zfnFENlf_~L^GU}Iit4)(m&MR_D}P#F z?n&tL8C)sVopR;5D=E&$#UoEh?>ia6c~SJCn9=j+=<>3sxhel_ANx*bWq`g5W~S+) zp$N=C`NK)g(mnape~fzV^F#3p3|;WKpi7jOJC~esozTi7I>1+0k8^_Urz7kcsTHnI;996OTOC&DPx9 z{83TigtXen|E%=x$fu8rxQ~jD9_oyw^V;jG)!n+CY3O7ZV7YizUsI)u?sJC#D!;O< zaf>!sNJzR978xI7d&@E!MmZZk3OyfmGx-uDJ^i`=EcfMIrz3eT*X{~;OaOPlPu9ld zp?70ylqEE#57RI^)A~$yyuDMTMEiVufmTjQb+?cg#=rJooQqpW!~u$(VHh1M6yhUhYbnD6_7CHoQtSlgV%(_p!Ys65fT? z&U5Y3v^VkXm0yP!_Z~f@gA5ti7`^xBh=&V>xGBHSoG#upPvzXrxer$8fIx;x?&l=@ zY$W|3NmS7w1n!MOZjdadlAnS9+O)VSpGGEo3W|tSpilyI{_+jD(@$&0^7Hdui9Z5N($H3J z>%EzKrH<0D8L#YWWIKeL2LC<0%=bxDRN?|Ekg07)bh^)%_LELf256b=nfUED5?)=NXhbw0yq4yM|pK^IEU9=2c6)RybVTbFV&WcH zOIr6N!#KS+-eqQGwLI<(QUaIxP!L|n)V&Fb-5;X%LzO4)TrKllxAjauAcsGHbVJ74 z!>{ljxM-sLGX$%usw$j8ps#MtR!_Moye3LRLxXW!H^tX_#adcg8kn1>vp;(M-3Zev zq$lOcK^!aZ+$D^f$Hm1pDE$4-yyrAH6<@tdBjPK1sK@$HG#cGA`qW1P>$Z-eQud@e zJ36`zrdS5oa<#L^j~j3WgL~xq>L~_fRFu0KmRwJLlIHtmwly4IV%cdt)sw1l)&%<0 z@3*xH6F-%$mENaxK7Cr_t@DF3OpMaET^Zt9yPuxIq;{I!#%9UM}N+*R-xsg z9~C*ZMPC@}s+oqP1FN+lO7Rt7xrhMt>iXu~lK@2_Q0a?xX_3tSyz1k^z3_)CJi6H^ z$2`f*Bibv zv6iKp@M^3etlp-NOA0~wN|&iyU~IJ32Suzkj8{2N zaLSXL`1tvARjD_0PA06`!{P7^joPPv4ta*<9arz@PbbRyy`v-T)C_PcZ!h*Z8dX@d zGoo{H&T*uv?-QSL)^oE68!yQ>cXV`2gFHi%PYdeiZA>b#j?rkckM{RFB#1kfa4U!X z#elPyIowe2T1;{qCvnJlk5C(OW%pftLRdr)IQa7NGQ74?CqHD~{_mst<=wOh>p|Z8 zW{rRC`Msjy@%Q&%bV&bZwcMX6=DMQ8ChJ?XD!VLVr^m?`L-wm8NACFT%y-6C_?+-) z4P%E-j3V~VgfU7Dsuv-MhQoVKJ4>1@SC=UalYUdItPg|Kr>^fKm%^R7nB{5TrcoQ> zzAs_Kf3C$l>_!fE|D`fnl2XTE;MPS4H*l2a@;|YnA4`_0^etLq_;57@nO4zKN}SBu z?(7mNnH#*o^5d`JJ%|Z5A)8ME=P%Vjs&)M)pGG{e5-(sFWw{ziD5X=_otOtD#4?W4 zdPn_QW${lGcTDygFs*oWDJhQ53qRiwTLk!mmB1N`nByQO z2$cT@AEtZgI^yX?;iVc z5Sp}7-i|?_14mSwB17=l`aVVsQoCp;1FM&CUw zO?y@vELnQ!R7z6rT8nc+ctKc6cX_n<23N}UbhO~haiiVA9jpTiS@R9V*?hRW5+oFD z6=Zp$KgsSn3`JZS^K>*=+{%|uHN}NWlIVY5My%RPr0xx0-OO%-V3gCfG1eYAT%51e%N@XqOVN-?L)BsxjY3eoxljGPNdS(V|@I_EMsa^CB3lb2Y%T2R_4jQzRoggs~# z$4B~kc3{@Woo{~%x}cXu#O0@HpW|5d&Iu#wLA{!iR!=iLw()PaT%0!^e2Rd-qpl3s zW9(}&%Ap+QD+%;)@oR&#QE^Gu1`-FgTJv&HiGs!=lX_u`2Vc4o-RjTJVLLL-C!ZIkHWRuc&9I)ZHesX8*^ff0 zH8AbxId>_MTs%@$<}xOr4(jxx*IOv^wyKjt^m+eBp6R+88RD9L-fFi9v{5=I zzs-9_hOX7<@fCS&TUD5D*XL{xGnkbnP41K%uR?z1hLPR-r;y;8kbnX$|Il7hl%!JX z+qFzTM;BSr^ZmK@D}C6#>(u*tSk$S@cD#?GV(X0;omK|hmnJBm3lxS?W@Ai$xgypN zS8=c1i*Lq&BI@*_BT*_ksysXTwsD-SKO}kjIhAP5cE;PfyCr#fw2)@Odp!aV&Nn|8zN${L*JJ7;ap{mJ)T zYkgC!FOkkJpWddLO)I3urpa?b&Y0|_85jFvlHCxX*1^HwgL7Ik7V@y1kGk2HO{l?b(rW@K6 zdK)mCI`340{Nxr-=0$zxh`~470}t|xD$AfSz>S!Z}Y7cwNPKD!_Jykjd>Z@#M-MyjxyB1 zj!8cL`erOQefseT)8i>Gia#e~?$!_GqypOaOia1kdi6RwRcR>@>GXSw<>9`4Hbyim zhFPR%)1>y(p>8O1I{MN~qNsY945<*QFdMe(Hr{j83m~p3c3G0?uccVDz$YF0G*H=L zDn&h~4HTyi^(9+CkRU``D!0may(0PM_PmEz^*nwbT`pCWCUPyPzBe%-^ z{fg;Ic)EU|;-=#4HNg`h7kzhR(7p6d7DhWe6kt@T?4n zG~eBjlcWn8R8BvRMIUR(^*u@TPQ6%6J-Sqm7NatpUu~LN$=;-_kvqNzDqa~* zruWuiciFQjMdi$R$&9cW)ZMo$2$>y~rVSb_hHATwt<|gwV>cQ_M&@Io@J_wFvWzGl zJy3~n({1eDB!y6b^;>Q{lPUrC-T1&ck}XT^*&Q#s43Cp+OAkk=d2dbJ5z^`m85x9(w6uY9_Kk1?x{l4!0rY_GUrAHZzb$`>88o%`>4 z%O1`!n0(vqb@W>t3r(CFb!M0h-_Gx@$jIy0(t0qKAChUO3^8U!6qI_6UNL89wA4-T zu~lg+Fuqbk7A8k^vi?+qd`;4onU;pH-wq)9b<>U}&VkR)_J{`%92Y-2tj75c#90s3 zzve4BnuM8Ael{ZKJw;k~1WMIK&W)yHxmTU+y0iqlXwdnS+cOPBGx0%_XOOwWqwoqM zX|-vMQoYc2zL}^-Q>aO7a{B0~#65p~SkULyj)tA12R|Lr#hN5BJ&ZWA&guH@(;Y_MZEE z0|wxXy6Ys-GmC4wU#}b@t)ZIGIPx8w`Zr%$pGw2UR0))Icj8PP%JHes>G;Undg|%Z zY>XcCAFUjv#CfWn(+n(iz-3aSG;+I3cS;qmTLns6!-I6#U9T|m{{+8yR=#fHUF@^j zNJm_@PIe8{5wGBE$>F-iEjS!sOT%ghn_b9Ql#xVTCazI!13KCE2sZUvb#PuNKXtl{r9W5FcBsrI>tUW*^*NjE+j% z9t)yVw>bJ5+Sl7LW@~3P9!#OGp*WZyopu^<3CfK^PT?VDx=<(Se zZ@U*CtH`<5yNEb%(Mr-g9u^5pejeB}Tv#9I6KgPEs*a2t7>|^#tjlhZ%*WFG8-d5p0d=X5bfD01-u1}d;7$OJk(`+eEt~M^S4fH1Xx7Xd zW2U|Mp(paDot|9WdjP{|BzQ5sNPAB$TFMiyJf+~DYM4FT1f*={jEu_%nZrTym!b5h zv*&?qN7lOPRHQzQ($QTv+WVxy@VvspQU+P$^#YHZ@?6K0sNfe+QeaHW)geyH__tb6 z(VnP5KsVtz*?*-1lwBp2y}dCF&9PrGNYIG+(azW4Tn- z*I{Y;y#T~zgpL(zWXQ)=vM?n-P1$s^t8RgQpO|Na%#FMwDN<;Tx;*z(j=EEG@cg~& zGd6$|H!$i+iUiB`C4aBfX}!-4>T7Q5suO?A$a;WxyUduo4Lylm;3RLwij<%W>stKz znlqV&nKlJ&%aZE+$Z?A`#5#xLEs^8?EZ;gJCIx#pw;D5P%CQ&hv*$Hc+T*k4{M&W6 z)NMrampcTaWe*271tAGPBb(eQnVa<@ej zH|)mqq)pm*Cav22{zsHGxBAtjVe1JG9}*f`j$J>>WPju`Vv>##6yUEgYYN29?8>ad z(upp~^+zN}<8!wpX@k_n#j2_jj!4jBT-`ywsq4OpLa1 zjn&ji^E8hTCZ~gwBkw*0PFykAYnr+(sEl{H!DNg7F<0hGZ_fgpci|NJRRwsZxNOOfqF%G^BS#$+17;<8P#+6R;GMk}e#A8(FnOic7Lam2 zD0r3I`Gzz`%7I~>7Vj40pI_bXRqIY1pDRBeRRSd>Ss-#AYPs%IICF0^AMogX?RrLw z7ZFn$qf)!~X>M^n;*HSAE|x@)0t%)T99IC^M0Szh$T@+JN9$(VH!w)kB{v7ftwa2! zm%J3J=h#T*ImWKntxA42m#EQoTy_NW=t!iZH~@DI6=S2)=?g+Yo$|l6U-oV)jYquL6cHGADdjwrzROeEIk%Ye0Uz%T-3#k7Vz`@FMXu0}pL1 z*nKwis1bcj969Wv$P5|L2?oE6*rWR!puR-nVt`_7=zU6;k(I=vX-0WjJnWGjg7Q}> z=gu9TFSM_cJ;~Q8hl{d~EG8}ybgv4qYo3%QP7X|5=|W{u1HO_WD643T$>GvHa})Qp6HgoZe&Q|OlH1cZUQ5h&|q7ADVJ zp6lViRynK2ax>ItM#)Whin`}l@iBvG7z1C+ub5akl}uUp`%ZHX#nWFW$@KKE7bx1tf6+rHo({1kPPM!&Fz9FNW;|6-}PnQf_kr79G0^R|0oPpq90M0-A3 zls!2xrYrfuunDm9FP5f#X+yqIf4rGtgz-KQSmy|I7$Q8tKNkPFMHk$2UF@!*zhX3` zoE?Mv9To*O+nQ0J&RjUf^~^w+5jITySLPBZJm@F)4xSj%akJ}Q)O_vwMCmO? zR?52xu z=ct`QHyOP{%Ce~MkeLN_E4%gCmABvWF=;JjbbFLb3@UJ$gvbzYei%-JipBFPoix6K zx|P-^@}T@c?krK@+6JD)d*U;5HPrJ34za;fAb+ynq)U!j5O6=s3|v4Qbhxu<$LQ(p z!d{)c^u@}beoX9YLlEcCzMp$kbo5x75}k>cow(+aR^;i)3?R`qg!U6I3kSHfeF zlE_l>JSLD(AQT}HIH~ffMsBi1W^Q-*Q2v#*9N;R9jtOyh!Fiowe?4c-QZozh`7vuo zITlSEe~&b&xNRX`NLQ7*{BYbj-OU!os)e1}zsaa*Qg@%wnBkrl=0hXDGOj0zl+pYq z?$l*@MVcpa;k70yct~)1)31F$=d>wK*^oCqkg%n|T`#EuWq#JYJ#YvRRUhATxxTjt zOF-6gJ{W_(u7ykfBAur(DO`iz(bUL5;KF=^(5eudeIm-v^5z(1J`~k97#6VIKmLG> zN@1?fG4a2Xo15EULQw?L3F%fQ_{zY2xgF(B6b{{eUZw2CFk{H~+xmUlhK5e23Te~X zuf*WvcfWxm!baJc3;|#pmRh-DXBH$C3YDeLTo6C|FJN=J4z{MsTqa%5RWD3uAffzJ zs4BFZ66I7RAGxVIDfRoa?bAR9TD_S^V4ttjtfZ!WAM4_^kQ@6*o303Fg)~8F zzr*0se8;ZCq&3k|O-EXi;$7kRmW3j=fHffPj6+|nUazA} zJeD{*Vvs$|!K=+6yX8P1P_F@u$yQ!kSV(Y0IA6}~S7DZ^ucRW-x%qA|0iJ#_@ky7+ z=xDt-x9jk##*6-vlCiheYaNYhR}TP6WvM`6o8x?WX6hjPpk003LwdhgLHL4JZ#wZI zG$Jf>yI;C$A>Q7^$j|%myq;z{5{&;%oCsgjHlo!+*)h2^i{JcG9ZtLbtd`ObKzda+ z8tG72N3Iq!!8Fpmt>z4gtyw=+y7Sq=o@Dx!_sW-XF;4>Xr8D8&%o~-@(pIW3;#Y!B zUuHbu@mQx>&y4F*5yKl?^LUZ23F&EhTx#JcMbBJOG2->J=OcJbPobHA@UrM6*=LeW z$cac`HRQ(M5DvZYU^rm!FG&M9ra=l}R%;;VGdJRDU2?7~BqMcE*UBHJ{H|(d{a5H0 z7k~ws`IaI3&PaJlRTuYk<+rqAiP>%u&rcn7X$Rql zL42+Z%;R>xWs$t)(Roe<$nR(dr)&KQT~c5DD|ykQ{magnLZmf zvTT_=kB|FfV3DVIN!OQ0$n_q2s6s{RUsNTZC#>yYD*cL=j$b%gLUgX4Z1&zKy7(m! z>f{N|%g&hU$WQaWgWJZu0aa;eE~w{5LiI z`%pN0qS4e*44wMJ_3+*sV!mw;ejRASKz$|5=y3$Vf4A7g$$uEDK7%C<;R$rm{hEnw zG&H63c$-@pOHJ=lqS%^d6nc{cg$W+kV;3k96}4ftulpD)YP%u8?2}Wd1Z&}M8XKu$ zdrhrsBjR-jsx0F_p+&tz1yj9OkMfRRo8vuj?hIcW1(Svy*J^tfx}ZzDeTcw|oX+@V zU#6?ERT5E5jM7_6<}py9zOR#;aS%~=Bm#A#Sf$`)yUa+cA2 zory?atX`p`(g*DXG0}j?9~7V;1S-!9Yk$kWlvkev1IP>Y?tOtLI8Gr+-yJ7u8ERFx zjmx3KdYv*SRG>`zW!fbrv*7N+qHoiQ9&zO0qu#Bij%1WwWAeo-!_2gTq}E03x|&BYaF|XHJE|}A2xMYv4|}S%sobjB9C5^u zuaRA!GbNY$d2HaUh1V-Btv!gcw4Bc=)=5)N3*21<8KtT8s&B9F@@Wo6QM5oCL(s$F zUWEbNw)5_VNpdeis^=?A+5=%=5IQPydk4r2D(^cUap}EDPoefI+bmVA`|f$c)l$ux zlq)U!Ks`<2iURL`%%ryxp~oaPVVl0!Fd3A7)!dioghmnXhNqve+0rOw!Yiwmko;tC zriVFP%FdVgz59?ZD2x8bDoVHJg+Fd8Z~=!F;o^{ zu0>J!I2wjedKCRT7A}?&p|8bw^~g}Rlvt{e&$mhYgz?(px`Qsq>g}Y%1*T5HPZz|q zrs z)bxE>A$NtL|I@wG?Qa7WRnHFe1Srbhu-q*j?g~bCC(Gqm;DQ`(30cP`b%YGoUDdQf)6TAJ-XUC17m_yzB3hKyq*rha)Dpx#$;1n&1b0zH#q)e>H zGZM2?mof0E8I%Wy`!onhN@T334l341D)mguC7c&Wd%7LaCsa~Z;l7%&poqbexYEV4 zE{Tk{ttlzsRVos^%FHw2KC4=guM#=sf|IsWC+fO0yr|v#Htu$Ox?lzTu0Ldw)RiDU z1;-K>;ZihUuU+<{m3YsJ7t9K@3D+1klbwwZc6iiST)Za>!Tv6Ri^S>pLjRV1%2E5!Nv18 zn|$KLCsCl3#r}yl$XGODj~Yd4*nZTx{IqoOsv>69N{tILKR3@Z${qfACBSB&M)vms zgV%WpBs+dn^xH$@tfP7clV_jnjR2_^Jxj9pigrp#g5yy!`kP8;Tgh*NfX?yIoG($c zx%-eN#JCM8UD?N)l2221vSndCGU7E&$hIUsxndJn9Ar&Dp291{jW?8!NF8Tte7xJr zOGr6BNckNAm!}*bvaGouNkDxM<}uF092H6Li^_IhU@5VZg(68_rm@Da=&lOG(Q1;2 zUr|(`ch{2|JBU~lL|ncBTh(Iq(}^qP;@&^D;c*KFdxGDWpGnVL`J$DdhQdH$ml)+9gLqh3FERdG1NHr-1#t2!To+!lr32{7j6x9+ zaj9gOuD-3VslBd-8HT%$&}Xm+pHc$zP(5tIZb+FqFLqUErnim(u?%eIYq9W%%JUvO zz3b_qm4`Kn0Z^}n(M5-aJPG0Nnm4r}+UpBP9;9;d@eQZ-7hc0(vt1FtP~OK3Kc zNZmH9wMwep`1Kr)wH>goymX5^w&P>#ky(4(aNmu}tsIJ2M4924!j!t}`{|Xlx2H;A zf#r$kzcMmvk88L&s(ExS{7iC;#!>0i$mlU)VIj9|8vc*x3)Ty(S!lO(g03158~wj2 zlZO^I3+z#sH0C4AxtI0Y)P1nIj*8@s^BarLg(AJZwhjs z1iZXSrKe)1ceU^oywchGv<&ZCgJc56wuaph4*3a>J%Z6X{g>VZ0%pyo&-I~V5{!DJ z_rk*P6CSP@lMN0R#F6A#zm(~!mgoK={JGcR9GNW(yJp5voOJIM(`{8!MKG8Vc&GdV z0$e<-rVLT7c?EJB`(Fy$c-7#D3L8Mj&lLkhWmm4E*q`PBb#WQJXm;Aku58 zqP{$90etuJ_*Ja#-V0`(Y{tl1UfWQ*@9*(Dy6oDiVW=XfZ94O<%HQbGe8Plo-+wth z{pR2M?QKKbi9kg&`;I&Ju(pY#x45}*3VkR$u${Yv>>a0feM_HcBbXQ`_PUYhgC06e z6kjgvP8%RFUe?(j-P6TiP ze0zIGOG zvHxpmPDT|-zy1?P19P89(IF3AaeZygXi;W8BW+VaO2%xU?O80E)KQ+5K02gt_<#rX z>GiZuTRLbFz??C&21M1wNPkfC|bM^M0WAVh>232nbt{;=0S@JoUx&|QRG2V}i z`eLQhPE-X1fO(1DEEjF3-ktkoahC^`hr%c$MDg^T0fbhzBHqcl33T4rH2%uJqKw}^ zFYo~JKb}wyy8=vIp8$Gw{I!c#Dl)m3*72e2;1hp^x&~wp3N+&f@iJ z>gRa_dCLvr`9Iy9VU*{(vGw%q)4nqmYR5m(hj#J}rGdZ7bTkQ%=zL z8I=Kw5o(7;xMVmWCw&IUNsD%V%Slx$=As_{kco?rF*6wT(A77#gNTw~J>}EeBDyUA z2Nj|x;&AMrS19?^$HyKYQqyOjT~&oMG?Y&!ulR-k(I9h5_w1fVJL>!V@Qrv!4#NfB zSbl!7f^=(7j4#*-oT26=8lM#DsM4Mr^CjM_%EMpR*bqL?jMLRL_%OoD{OBrEjJ~H8 z#tWXAWof8lpoHHR-Zv%`{#Mn<7v$tPi&#*-#rXQ!SFj0OD3)DOG11YoQsK{yiAkPM zUNYqHHr;InIBwd&;1EHR(Ql@MB$DTw3PV07Z@NF&e;Y2fBBjgelp!MFfWw9AYH5j9 zDsa^g$Vflv)Y2L-c{J#L`x-4gADEdTWudw_?H(iW+*w7Sj2IIgxhOegKB^f$lH^$z4bd@@ ze^nA4rTc?$z=B5ReET*oAjmcz^5}*9->l&8nND1yRa)RiREfWOWM(k)h2E|8|FX)Z)}=)un$e+JmOM&gf+9j=o93#j}# zU))u2TL8l8mAv7GE0J1U&X-*KJUDB^_j(L#>FhV_b}cv$mvUN-PW~2-WLjJ88A8y@ z?Kd8;NqE9?N`%Dgi>7)Cj{q-+&WB;f#~IPN671eSe;{+hMFj#$5>(WHmXZ@cPlw4TMYKXU)^<;y_L6?>P?5BOiodj8_H-uFwK$QG(5 z3b8%n`P$79jh$oU7U2qFH-H~e(XN;z69?BxkADod6A&No+1aiMYP<==%o_BoxQR8m|r16}WOqo~F#qv94H{-tTu-058eQ<8qY!r(%7H-PJYQ1SGGjIxu}cXmHb1 z*VK|fcbPauLlP^$lFjHaQe=iPUlewer}Y%DUvW4Hj@~`o<`xp<9X1;B0jDFF@7|E~ z9=ymQ`RnoPjiPy$7=0y3{_k>t(>ARa^M1~R33jh~c4zK}OvlQRSozN5qScTIf5o`b zDvW2Bq*NSosg9vw-4?6^>@?eDg9$i3nhJyzVspy_v_Y&w4@!F}b@%qie&7E1`&nZ2 zR}@gxkb6%~^pX_m0|4N0;2#s2FlEVGGqn7dj&vDNPjr(z+70b8+uQDdpkZ5c?L&k8 zzQ^BCOrGY4e|eGPtZNEqi6npq)-(0M?Q%Yv8}nGFGTf;z+J9lGks(B*#SXbCvc5SPb* zxZGi;u{le5fiOF``G#z#2Z|8*bn%AdtHQe7>dY+b9YG#I?pQjpeYNIf87 zhOH(kGyj|Z`MuH|dcaC?fDKGioYm1mXCCutDc7S!t5=HjDv@6k?SPQji8t*fpJ(m+ z;KpC~*`z%`&oeWX(@DNxaWAaDHwm!hGw`tY^!|@&?+&IGZud2#%w_ApjnL5Y+g^ts zaSMf9wBOnaA&dlR>l#32-$yXS2s^Sc9+(9;2G8L}cxC5=U$#$nOD1I}OjH9>eqHUU5d>#hc!3;c$(ORo z<4OR;3M|1%8{MkWCaRi?S=2#HfQgikReeAf5-TFf*~RO+rISXdts@69F>>tG%`2PX zeyaaeHwF(S#_A2Zx2n4gFIRAS8+)4Tfi%@j-*qL)PQ?g8XZ{5o9#==8R9Nj<;-lOm zz|+yD0sisY`QKPMaiUiWI7(7i?KyNnn$PS40Lg^w=*hy~`Hj9=F$94Qz{MtF<)fd+ zxFCF~dJP2uD#3>1iHcT$!x8J2Qqx5w0})B3UDWjl)}tBij@2Nd)z3uRY_^1nd%Hwg zn;x0%yxOf5wAeuxKain|U{lxMgCe>;y2eOiuYQ~pPx;bVFyXc9)q2jzKq*u;{^4j# z?N+c<_x|}Sd4O1`27-Z80}FoHj_tU?=GrvH%o-J0ylvtFCKB$M$G9C{bvt$$kDK&Z zsV>V8%YCWP5c>WB*vcQ)@{>I$o>9+_h@uFjnIGlo;J4 zqjG!gJ;K9NhkcIcBK=CrS7lrp!o#S81L{VePcd}#gOlARUgMH9 z4B^td`dB0wmivCu*0KJ=`d3;jCSlbCu?f}$LoQGkUfYBwqA`1Uz58`)lz!c-Xu6m| zU5IL}G-cd*x1ge~Dia6UeM}nEj!80_Zj9qic5l3T$Jl{3l<6Y>ph1;gs8sh4l}Lw~ zwB|`^xa+E^7nR9>J=5a!XER{;W` zSoRIWY}%_dmj!hToLDkmf;&l&I|f^IbdQ-_{@PNOtqf zI#7me53KU&f*vZyqh9GG{p!hnV7GHkD*7v-QOI9KQp8^?-cLFD!SmQ8sqw@*J?1{V zqdF`hy_No+TlHu@=L4(H>{7n{Fkbb-r2SO{VQf|a=3+eY03g%t%yBE_a07cjhxFQQ z4d%#Gx4I5?w&DbMHapOTqXp8Gv2L#+LY43!<8Q(#wl(yD^g~q4*eW&eiTw~k0&_eK zTz(3_kjwJ>l&}UxaG=j$;jI>fTxK?&!Xv>a!v%sKCYq{a*1`XDexGxjo zxD1~xeEU?PJvaWT+-H>M;AX+iC!ikc-jpLiTa4(E`lH$D#d)bS3uy{mdp?K)duT&| zd>SBVe*R3Yyw98q*z+bt6fGa1yQqWyW-_En>?|ENabdH>S19szQM)pB*@)?G6};W2 zhwOT*Ox=9?eNOo)k8De%tf|IEQY$Q=4}sFIpB*2ur1=_r?btr4()rZ ze>>4Z4&vSQDGez=^ebxh$5}-i3?y4Pz~pHsm=z zKogMbA*GM@XD7}m8Sbsv7vft~jU+Dw>B!9nDy~s-kV^m?O&HnK7JjYyGF>91C7jdo z%562L85~eF?3S>atIXd$I@?L80<=s&g08@T_zE}xRRJzlnbz2pFB zP4-wYaFfoQk1nVN=(@|32t>O&1q<4bbKvXxV42%ypDC5%==RI`_5sC%Lq$QwKe?wTkFS@3A_^C7b#w_5N@h8vbQMVKvT;i& zgv`Y~_2C@aY;ZI3ecI&L*?@gIjtB1E6P+J_%=zkFR{5WU640OU*02Ja*EbNQ27zmY z$(NQrt#Z;J$mKycQI;?A3Dd>it_%4hQGP1VGW1*4HINVd;2y40lQl9EJ?b+5BC2q44gP| z^Xi3BB%jUerMo}sSiRx&Q3^slW96$+K3klQ;rk2~c)!YNWkdswY?1n57i?EOrKag< zh7(>MbS3tz+v*h$kIY?Cp^S|ll$z(3-_?NogZfLSW$uG6|I%>I@mK8X5(0P+;vJw$ zCgQ!Ox4U?}Y=U;LQcD@-hDIto1K@AM7+uJ?hCe}Z^{~* z`5js7;eonl7ob1!f>HiZFHan9^2mRVRFL55Pn3gJ-(_UHb!$GkbZykyYK(@(yGQtF z(p(JjQyx1*o>^O@tS7ykc|Brhr-mP{BY&fgrcm2_kFmc~gAiiMagWKQ*i;3~DBK7R z&z0W)&O;G7J}_jtD!sMAgssttS#-~ufS!#R5|SQ`%d87M+odemL{T!#7)RzOR4Z9w@TH_AH&(iIS{EmuER>G zkfU8kUn|*zO&hP(d|XT{+xbt5hKBE`J;!fKO?EOV#`AxR7k&@)g9ErI|L8#TLXd9$ zm^F*>>s+6el(jM=Kd~X--N<|0*mcilUynUO#Qy7ee8CWQa@f>oO1O6J4Q0xYs?BnZ zI>8Gs&o>IklKxz+2L22L13=;?9`Xe!Du-v`Q;tU=!iPb(rLaGwdgST+8+DEFFO|bG zjKV5jL`Cc3n;7aXS&TPe*zK@4@HkFJlYRdw_u;V{K74;n@#!)^^S;?izs6`=74Q`> zMF_FDHERq5<8@fU+Y<_pwyYc}UbW)!p3ha<_k8P`We(b*BmJ3J*m|-ecDwtHFpuZj zsKMH!%uL*_o1a$#_2Ae!x_0LmS7)~X{NI;ne~gle*7o} zMQGr9A$rp0z(h~?beg=}$yJ{)>x^B0v#OAatlezUqM++*`i%B`dN{{YsM&%9y?W0H zY;rYb_A^KM_oJy}@92snqusg40es9KHt7#)X#=~|l7E&coYk&zwxun=WMy5&SBSUA z+!_7-YKy;oK~3L|i8HVO!syay!99I>d9~N&v-`y_j4I&unOO^G_5SR?C$j$slE7a0 zvp?RZ{-1a9-^bYh*{1&;RQ*QW|M-;OmIpZZKQ9BgM{d|v2*>>Q zkqpfFak@OnUm>9aUIC=>MgT!Yk*GAu`|p7O2bGo;Q{(}yDZFgr8d!0sGO0d)Xcg_d zD|JXsks6pP;Ke7yn!0oEpU1H85ULVu!wMP$lasNZWq6NAq(>R>c*gtqN{^6Gwmp<; z!ft`8$13bM!MRnu68=vRUsCV32hYi;yiKBC&b+vz5EwqPOO%2E!92#iRTz))3A}YX zJNe3co8$QEGkC0HJ!}Fq!5FD!Z0%>@5ltMwKAK&WQ`YoarIr7Vuq(a|P%M&J2kYxYVYBvtn4O6FNSz3(7 zOf{O}z zHt`BHLE~(FW5nj{RMBYZqCP}5i8x-4pLCyfH7c2tMsEt=9|_R;S_Y%2CEPW8ubTL% z4=;ZIhrTi%)s^`?))TM#deP}VsNJy13aIso!Nyz?=7_T9EiVLx3MF~J_4xvqkJt7c z>khKCr_|%NvWOFY-%O0ge23R+*T!+CuYJnw7C$h^ylxGtQwFZc-*v1&;LR6@hQ!Aj zm7d=blq(P)Nu>}OA@8W#_bI#{Ezuz6>-f{034hQJoYt6aVjQ4$>=Y3`= zH!lFIUSF0st~xwcmm*h|)QDU%`&y=*m>IKGAtk*3Vg!ynrD4uX`A6Ql-v!Ov`r7vk z4lq)MI)$``x|O`#Saxd*+fG53@+0Re+48&{(SHp42iau-AXYT90ic)$SeFP7r;b!_ zu0*gnit5)gJ!>Qkl4`GOj24vqNWZv5joN@d6OZe|MgY8_XBkx{nAWE4Ok{jL8#i`LXeOJ7@N)mzUsmr&Q2ek|+(}@vE9`!_yU<eC6ZGurl+&48DVQ0*|fd#jjG0fif>kO^HoA zA8x9*3mQY%%Ziek*fz%%E1gm$U##9+`9xJY;?B#b3H1U>3E1uOJ0sX<``tlhVlMY^ zQ?o7iD6#A7HNeH??=HN|?4zcFj_*cGlaEiCj_5tgH-aisQ#GQ>KhNLX++Lb-U9Gm9 zE?9s7g}iUgr}Bqfc7IH|%!)4xEiLKijD-_&ykEJ(IP66yUKT2$QQ-&jZxlPA2JT?9 zSp2~-BJE!Kl#1R0`cRZgHHGO~qBhm?&H2|7Bh^Wx0W4!_(RttIIx^$%2|MtX8st_z zIuA)nc-`B2jg5D>>jTP43dRfC&Kj7tss;fJ-z0A!+&RkeM>8hl@0~z{Mq3=eQ@?84 zOBVpgDk#y_+Mn`foG&)4E@?a-4|t06{xq>1?}X*x+d5@MkK`#5E^cGih56i(Aj_um zqr5|P-Wu2Y$M{bkbWbHu#KtYj5ZJ9K$>~3%%N2kMn(~)Jv{DVae^kWh%Aar#u8-Ti)+-*XbKYpC9)U`Ov+x(NWTRhaf>+F)iGbH7+y2 z%*0^RC{)x?SyW=_x`NW;^u}+g)e+@=sWs{<X?_mFM$tuQlyoSh|&!-KK{Pc7m>YCRx%R-G}^3JIm+%tCg)Ah!LwoSETTbaU?5w;|-rP z_k>;jMvVVbyFQG#zBmyQY;y1T-*dA6C6E}J4-iK;7tQVeW=;I}aLtwjJfk*Dm_&0+ zN)Rue{HBsv&5fqxs0ECKjy;J1mUYs>L6(V?b&Z{!or#(n;cqcOwGIad2NMs^TJ20p zX&P|7iNXi@r{64UV^PtftlUU@rG$o(lHuj$<==#MNJdG==J)Tp99|={8miOs(gAKl z5rFXrzOA-)`-Nj17Y~n)s%l(g$KUtCs#cv%Dihk8E=i4| z%8fYAa`vykUFBqt>j6v;wryiYCv={@=>-xX#{2tD0A9*RW%X0Bq8QG9$+^HUVHnEC z@3fgrBIrHkRcYFNc$G^g^qIj8N>_HwGK(N4LvPt|-$f1#TbHFi1}3YMXAQ1vBCd9+ zI`14w<{kerO999c2%-V9h`F$2_M}9oJiGt8gYU%4SoOjv=1F?_lFR%X?<>`v37>`4V;O^5%LU@-V*~!1YR};avi-?*HVko4k7fi2=y8J|pew1{dW)ChT&H&NF}5 zxMsw&;uIGFRBoux&a`}_bxU6@@%Y&Xa1DT~#Y&sqQu%=IZvrJCvcZ73tAM8$r>ux; zbq+hq$vxh?4wBB3)@0d*c-~)=kP~+Zo2WzOVN`ThPXiBsLEu||dEhSrH3I;JHYzJS zVzXC+d)^+#+MtluSg-#45?7#P@#(X@0@Lm@KA+q4%oO7}10R0?&PZcaOMe?knlvu&K?qVDU=?35~V+DNC(+20kKn zq69Lu7FZ_K)6@V z_1q;VG)Twe*SZu?ZhzEJ&Dv%HSc2GsV=kO~`i2^uuN6IP=RaJ}R(jji?u?#}SAJ%% zJw3SaahnGUB47)ZK8}^lU>IEE#9qHy8k=L{isMA(p)V3?9S|R8rC`v%Fa26pFA=s@ zi-3x^(0;K3V{ikcSED+njyud%rIpS7747G5=QIFkG9YxEV`=}XA}6otyi*=6^Mc=g z_@V5F@w{QO`U2qT9tt5^cQiX4L{t-9ZOd2D>44aI=N>>_&wo%xE!OREEZ36r=+_sjdE>s=QH&4yQ!_! zt5TcpTxvigW1I6~p2mG(vg!jdk4*ytD*lr5oSr$q%b^R;Tai)IBt5gZ!ZsWJcGIZa zWBb;PNdEGIqdEYUYW}j<*m>Q4xZ>Ky-$|3kxu?*&G2W^>i0hT*bcceU+GeWV40c(X z@Ue|sOMeF#Sk(!;4Kx{aYsr63l@|eq^9+!J{JoL@Igp36)9w%Dr6&70z+|pT@x*1xjaKdLoYjRL z>cZ7%^x-(_!cAYaU_HnC);8G1X7KyXyXY~wqgPZa!~h`3ax+=waHsTPlEG>6WSugz z5o;pqeJdfZdVNKz`CO(~Md}Vvn^VWE)7V%}#^o-*bY4PpHT1^Y>LD%I@$10`Om2i5 z@&**^Y=rHha$LIczAGy~6^*k7p zrxyr7a5ts^G+as$Izx~`9C_4FZ1>@D(l$rS_hCkx>v3sm>gQ_oKTnFw?W%}v+a_rg zQ{|V(UI&ZcFU104O4-?D0@n(~@qDJa4 zA`3J$M!jk4UfL{6rp~|jOLSK7A*|ZTZqWBSMCa+t5O!7hDLCV0V6R} zcW%7BztD#XcW!!}2*}94dpA=AeoxC?FzHgD zc+Z26<0wuwr?XmuG*9 zP|i9Qlqs7w%TqRk9NvkSfVtHLc9twoZ#f`9gEjg*eI2e&#z}x*laT2ZKXQ!7dT`!o zoq#Fn)+Vm3vP?>e>t0P%f=oag2x7Q7uaJuXV^uRpd0glGEjw%3`)bp6(${*h(ayS9(Tl^1V++MMJ+>9{c?pq-kn?9s}87 zhHFj;P{2EzA{;YW4JFcPRLHuEF4I2^Y?1WP>9|xpKUk@(cw>sq{PreB;J7dDJNq&N zNnF_B!3P&*W5=+P%A8{D?NKi=LhbUy!9JtRD&Owkb_Zi!| z;iO(ko11t=-Y+7S}z9q1`AQCarlnRzhq#|PH>5rbZ3~D2^ z9#j)<^h~rG3^ftUMCPK(>mS}>vL1?dNz&oAU1V}y1sC$6T5OkTv%lMv*8bH^Q9q`q z6Py#C0VLr=daf(X7>ZdHX!#lZ7j(Vwk|Ry_8!ai~Aor@37gKDJ_iZlTs4$C~^$V0A+|ap&p01Un{(Q^`j40_G#!&jInIN)`Wmm;*m~4t-1$zg4#0S^GvI)?iLt!#Ee+ z4h}jPtd7^*!PcxqR5m9$3}TnUIk@mj4wtKJb}V#!x9_k>(lV zv*8|TKSI^DW@gfW@-@SwZyfRkSN&!XIqBGgbk8>)pG*_5v0b!sjiXX=W_H;u4onZv zHg2fAFqWoCBIJJ5L6CD&7ZIPLJc|QjHtB;Hw}gVmtlqWIlDAKzLR4NZW3BWWEjSI>B_w#9iLxtEBaNE-D$%#Yr<@S>4LJjW9(RJ+kxr?Ls+s(V{ zLRouz2zxkM@8PJ++nJdeIc@DvQuXy`-(6g1Q?d-0z+j06>{Z`l4Q*{>p|;@9 z=L}A6ZeF_!)KPm0iF)20;k%2CYZY~M0O2sbSRCl@H#=P^-9N9$p#Q;=dkBTTooF8( zwt_?`0QFI5XYH5dPEOzSD!F}X7t>`zx3}?R6vj9^OKCG?dY=h&j*jY{Egg$>!Je&J z?!dG&E<4FAEeAZfJ|8n3w>olQwq?C#sBU83k=BD3ErlQKvaA52Fv=yMuEgl*w3$zoPN#EGkaM_E@ z&o7sXm$w((YVaICsnnc18NdJZG;H(7dS2$mpp2|+K|p}`y_j=jSh{j}T1MIzQ=s-pPNZoy7vOHhR&c zMfK-oAN=7*gC%h(EjC8w{-axJ6Yy?GG`NLc)V%x5FyWOf4iqlogD+MBGd-N0oog(o zdDzXz(`uad23B&TzHi`c0+ucsSVGocJ?R0UF+M$AH=)7jUZghj!gT-Zq1EFhMO|IL zw);B@?K%qxpfEqT>UVOglarP%3bp0iNk82zDZL|abvb0)DW6R_tLqYNH$|yO#d~*L zc~ZTbnweQXb_8LL0V+R}ld2_eh58ZUcXD18S3p!qpF4JLr(CG=}NpcWf zhD~;OtyJiz9TE{>+Mr%L5N$)RXVmSa^8* z^l)*zUA~xSdXL916n%u#cZD)g>Nd(${WGlYCM~~|G7y|8>rea`Zj9aoJqsG^F zD_%T0gqBt&F;+CmVq?du@yV0NXYo0=guehsb-A@1_b+Wm@T?|cQ644w+-#U#R^IbT z30+yF6dw8`VGNPoeJEab7|CFFIk+tuy}5*e_2MP!;IAA8Nb<(KZx@&xgWGOS_8EG1 zgCEsWu&~rGwdYC2sm~xtD~@vxBp=E2a=-hPbnETCUc!Wi`i&D(Wk~ko#iv|Qx}j%? zz?Vt6oSf=R1XtRW6tJ0(%1ok$uP+vZkF9NvIeAm_Wk6p)P3iUB-TL;a9BzA2c;H4+ zk=xMlaNNg_$g^a1{)eYdOXuZ3zpyf?YzQs(G-XI40c@y>B#}JDDBKlXl|@8zui(sM zoWbVT<=xBVqKv$Rhk>Po6dop_vq?_1ETyav$ZlADQ>6k0Q*@R9Sf!^YvPkG&D*m0%=7V;p+R3|X>BH(JPvKh!E50< zWnXtT$(bIM2pRF!6+KGESejGgei>=Xp zmF-PTjN3$OZpM%0AA+B6Hd-OB@TbA&lZag!aiGpJVC!dl`)K&{K%sMoPt3OC#1A4a z^Lmm(DB>^XZjUH%uj`{z&yw=p+&r9FjgPy+SMPWpvqe^c!h1h$>qUu4eP6!@?X zD(_|9o)@sP;c?&0p);_eOBDy%6A=-aY!0%WRQdo0J0C=cM;L)%OIv&4sJ;FM=DOhvGtD2(9bG~RY{mN7LC}fyJZ1!jz;!7T#nD}W*>3%%J zJ2ur_H|4pOfTZ|SyrCE})NT!N#nR!ZyLZY2;7L5Z@oFVlcum(kA$gSez-l;El(4}f zRsdmG=}r8Q49AqrKLST!EFCNpc-fV1tgOe{mlw6z=8NUmVZkwBi@j%a2lA1SFfFkW zP-QCc;2<{2T^J)|8Z{mV6|}TS;*$G=yMD3RX^GG2eC$TFJ_pitCkvBoio(5sv_BVkP>x$6_mzOEH%$tIg!#cj-eu*)5yK~b| z_489nAcNs_MEydWMlN9P;CG{O6LKS~5+v;~_@$p?^YMDn&a2WYUOB*ZidVR)U-!EQ z$`@7v{!!j-a*FR37#jnT-abZOzHy-Owz5I&zmbT8+sDYZC8FR?!(dofN?KaE9jwU) zo(4b4%IIn;)=+PP)``~01>kNpc8frx)T^2V9|(}P5hm~_SUET*rfL5Q_|VW1>t$xF zTq?%G(l68f$kl*!E>Pl=ijo!u!uDEF0iJ#Hr!_Myd790}wO&2}G+J~0&?_OLP@2iZ z#wd*}RTY&j*UnaHLb2J|S%(GFmBuu<;^Ms;j|+Y6HaEyi2aD~|f!SO2QlYrhiTk|x z#JBfE?QLzkDe~uoR9) zl>U5o4^J+`Pj1zauT|qhHKT0S{Pger%~G%kFhxoos7Yxf^%BS{S<;H z@4__po8U4w8N}M~oY_Jy>7)5=6cV zcT1Q}(#E(dPeH)1)g%RvboK1C*EakcVUF#`L84I(c?JQ-a2^&Gi3~<~%*%klo39$B z0;?o#)_m>~Y3zLN!?GBfk_aCke{{Nb{7C;q4CA)<^l)E*Sv+ldtPEc-TT^LkqAmUr(?P8u%bj?le39@lFV}D zB_jOAz#|{Cqc9}C+D<(LhO~-`Jb|n1dv)8(@lpFbXXBSQ1Zv4|J{IK`(d}P6>1vu? zVt0otz(?b@iR@A1bI9K(5z9J0XqC@3oNy)kb{$;3Fc5ix>=?Q8aSb6^?N`KOzPB<` zO-4)7;c^BWt${V5kuuk6JwnfM7{Xt%H=?lrSE?RAdG%U36sVrc%(vLs{)!1{*a(wf zbFIl9JE5R^oxGP}s(kt@nIl5SD9KPvHtSLGx9>&3O=ID&pbC=c~G6JS!$Pl!) z7EL0fBB(?rzY+I(Gj5h46$wkk=W>LLG!A(Ob;aw#t@-ApH2(5r-uO+abZ!ab$tV@&!tAirEh>nojm4FXj(2^o&Px7enO�!BQ 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

kwU`LG1`mIfYVT4*b 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%0AIR@97uI$mXb5rvm$BWPv0Ws_awiE~1-6abt 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 diff --git a/airbyte-webapp/gradle.properties b/airbyte-webapp/gradle.properties deleted file mode 100644 index 737005e687a27..0000000000000 --- a/airbyte-webapp/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -dockerImageName=webapp diff --git a/airbyte-webapp/index.html b/airbyte-webapp/index.html deleted file mode 100644 index 1389418021201..0000000000000 --- a/airbyte-webapp/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - Airbyte - - -

- -
- - - diff --git a/airbyte-webapp/jest.config.ts b/airbyte-webapp/jest.config.ts deleted file mode 100644 index 39f03b7089dda..0000000000000 --- a/airbyte-webapp/jest.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -// eslint-disable-next-line jest/no-jest-import -import type { Config } from "jest"; - -const jestConfig: Config = { - verbose: true, - // Required to overwrite the default which would ignore node_modules from transformation, - // but several node_modules are not transpiled so they would fail without babel transformation running - transformIgnorePatterns: [], - snapshotSerializers: ["./src/test-utils/classname-serializer.js"], - coveragePathIgnorePatterns: ["\\.stories\\.tsx$"], - modulePathIgnorePatterns: ["src/.*/__mocks__"], - testEnvironment: "jsdom", - moduleDirectories: ["node_modules", "src"], - moduleNameMapper: { - "\\.module\\.scss$": "test-utils/mock-data/mockIdentity.js", - "\\.(css|png|scss)$": "test-utils/mock-data/mockEmpty.js", - "\\.svg$": "test-utils/mock-data/mockSvg.js", - }, - setupFilesAfterEnv: ["./src/test-utils/setup-tests.ts"], -}; - -export default jestConfig; diff --git a/airbyte-webapp/nginx/default.conf.template b/airbyte-webapp/nginx/default.conf.template deleted file mode 100644 index ee2c2271faf1c..0000000000000 --- a/airbyte-webapp/nginx/default.conf.template +++ /dev/null @@ -1,55 +0,0 @@ -upstream api-server { - server $INTERNAL_API_HOST; -} - -upstream connector-builder-server { - server $CONNECTOR_BUILDER_API_HOST; -} - -server { - listen 80; - listen [::]:80; - server_name localhost; - - #charset koi8-r; - #access_log /var/log/nginx/host.access.log main; - - add_header Content-Security-Policy "script-src * 'unsafe-inline'; worker-src self blob:;"; - - location / { - root /usr/share/nginx/html; - try_files $uri $uri/ /index.html; - - sub_filter - ''; - sub_filter_once on; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } - - location /api/ { - fastcgi_read_timeout 1h; - proxy_read_timeout 1h; - client_max_body_size 200M; - proxy_pass http://api-server/api/; - } - - location /connector-builder-api/ { - fastcgi_read_timeout 1h; - proxy_read_timeout 1h; - client_max_body_size 200M; - proxy_pass http://connector-builder-server/; - } -} diff --git a/airbyte-webapp/orval.config.ts b/airbyte-webapp/orval.config.ts deleted file mode 100644 index f32b8e5fa7691..0000000000000 --- a/airbyte-webapp/orval.config.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { defineConfig } from "orval"; - -export default defineConfig({ - api: { - input: "../airbyte-api/src/main/openapi/config.yaml", - output: { - target: "./src/core/request/AirbyteClient.ts", - prettier: true, - override: { - header: (info) => [ - `eslint-disable`, - `Generated by orval 🍺`, - `Do not edit manually. Run "npm run generate-client" instead.`, - ...(info.title ? [info.title] : []), - ...(info.description ? [info.description] : []), - ...(info.version ? [`OpenAPI spec version: ${info.version}`] : []), - ], - mutator: { - path: "./src/core/request/apiOverride.ts", - name: "apiOverride", - }, - }, - }, - }, - connectorBuilder: { - input: "../airbyte-connector-builder-server/src/main/openapi/openapi.yaml", - output: { - target: "./src/core/request/ConnectorBuilderClient.ts", - prettier: true, - override: { - header: (info) => [ - `eslint-disable`, - `Generated by orval 🍺`, - `Do not edit manually. Run "npm run generate-client" instead.`, - ...(info.title ? [info.title] : []), - ...(info.description ? [info.description] : []), - ...(info.version ? [`OpenAPI spec version: ${info.version}`] : []), - ], - mutator: { - path: "./src/core/request/apiOverride.ts", - name: "apiOverride", - }, - }, - }, - }, - connectorManifest: { - input: "./src/services/connectorBuilder/connector_manifest_openapi.yaml", - output: { - target: "./src/core/request/ConnectorManifest.ts", - prettier: true, - override: { - header: (info) => [ - `eslint-disable`, - `Generated by orval 🍺`, - `Do not edit manually. Run "npm run generate-client" instead.`, - ...(info.title ? [info.title] : []), - ...(info.description ? [info.description] : []), - ...(info.version ? [`OpenAPI spec version: ${info.version}`] : []), - ], - }, - }, - }, -}); diff --git a/airbyte-webapp/package.json b/airbyte-webapp/package.json deleted file mode 100644 index 31bcb50171175..0000000000000 --- a/airbyte-webapp/package.json +++ /dev/null @@ -1,215 +0,0 @@ -{ - "name": "airbyte-webapp", - "version": "0.40.32", - "private": true, - "engines": { - "node": "16.18.1", - "pnpm": "7.26.3" - }, - "scripts": { - "prepare": "cd .. && husky install airbyte-webapp/.husky", - "prestart": "pnpm run generate-client", - "start": "NODE_OPTIONS='-r ./scripts/dev-overwrites.js' vite", - "prestart:cloud": "pnpm run generate-client", - "start:cloud": "AB_ENV=${AB_ENV-frontend-dev} NODE_OPTIONS='-r ./scripts/environment.js -r ./scripts/dev-overwrites.js' vite", - "prebuild": "pnpm run generate-client", - "build": "vite build", - "pretest": "pnpm run generate-client", - "test": "jest --watch", - "test:ci": "jest --watchAll=false --silent", - "test:coverage": "jest --coverage --watchAll=false", - "format": "prettier --write 'src/**/*.{ts,tsx}'", - "storybook": "storybook dev -p 9009", - "build:storybook": "storybook build -o 'build/storybook'", - "lint": "eslint --ext js,ts,tsx src", - "stylelint": "stylelint 'src/**/*.{css,scss}'", - "stylelint-check": "stylelint-config-prettier-scss-check", - "license-check": "node ./scripts/license-check.js", - "generate-client": "./scripts/load-declarative-schema.sh && orval", - "validate-links": "ts-node --skip-project ./scripts/validate-links.ts" - }, - "dependencies": { - "@datadog/browser-rum": "^4.21.2", - "@floating-ui/react-dom": "^1.0.0", - "@fortawesome/fontawesome-svg-core": "^6.1.1", - "@fortawesome/free-brands-svg-icons": "^6.1.1", - "@fortawesome/free-regular-svg-icons": "^6.1.1", - "@fortawesome/free-solid-svg-icons": "^6.1.1", - "@fortawesome/react-fontawesome": "^0.1.18", - "@headlessui/react": "^1.6.5", - "@monaco-editor/react": "^4.4.5", - "@sentry/react": "^6.19.6", - "@sentry/tracing": "^6.19.6", - "@tanstack/react-table": "^8.7.0", - "@types/diff": "^5.0.2", - "@types/node-fetch": "^2.6.2", - "@types/segment-analytics": "^0.0.34", - "@types/uuid": "^9.0.0", - "classnames": "^2.3.1", - "date-fns": "^2.29.3", - "dayjs": "^1.11.3", - "diff": "^5.1.0", - "firebase": "^9.8.2", - "flat": "^5.0.2", - "formik": "^2.2.9", - "framer-motion": "^6.3.11", - "js-yaml": "^4.1.0", - "json-schema": "^0.4.0", - "launchdarkly-js-client-sdk": "^3.1.0", - "lodash": "^4.17.21", - "monaco-editor": "^0.34.1", - "query-string": "^6.13.1", - "react": "^17.0.2", - "react-datepicker": "^4.8.0", - "react-dom": "^17.0.2", - "react-helmet-async": "^1.3.0", - "react-intersection-observer": "^9.4.2", - "react-intl": "^6.1.1", - "react-lazylog": "^4.5.3", - "react-markdown": "^7.0.1", - "react-paginate": "^8.1.3", - "react-query": "^3.39.1", - "react-reflex": "^4.0.9", - "react-resize-detector": "^8.0.3", - "react-router-dom": "6.3.0", - "react-select": "^5.4.0", - "react-slick": "^0.29.0", - "react-table": "^7.8.0", - "react-use": "^17.4.0", - "react-use-intercom": "^1.5.2", - "react-widgets": "^4.6.1", - "recharts": "^2.1.13", - "rehype-slug": "^5.0.1", - "rehype-urls": "^1.1.1", - "remark-directive": "^2.0.1", - "remark-frontmatter": "^4.0.1", - "remark-gfm": "^3.0.0", - "rxjs": "^7.5.5", - "sanitize-html": "^2.7.1", - "sass": "^1.52.2", - "styled-components": "^5.3.5", - "typesafe-actions": "^5.1.0", - "unified": "^10.1.2", - "unist-util-visit": "^4.1.0", - "url": "^0.11.0", - "uuid": "^9.0.0", - "yup": "^0.32.11" - }, - "devDependencies": { - "@airbyte/eslint-plugin": "link:packages/eslint-plugin", - "@babel/core": "^7.20.12", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@storybook/addon-actions": "^7.0.0-beta.36", - "@storybook/addon-essentials": "^7.0.0-beta.36", - "@storybook/addon-links": "^7.0.0-beta.36", - "@storybook/react": "^7.0.0-beta.36", - "@storybook/react-vite": "^7.0.0-beta.36", - "@storybook/theming": "^7.0.0-beta.36", - "@testing-library/jest-dom": "^5.16.4", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^7.0.2", - "@testing-library/user-event": "^13.5.0", - "@types/flat": "^5.0.2", - "@types/jest": "^27.5.2", - "@types/js-yaml": "^4.0.5", - "@types/json-schema": "^7.0.11", - "@types/lodash": "^4.14.182", - "@types/node": "^17.0.40", - "@types/react": "^17.0.39", - "@types/react-datepicker": "^4.8.0", - "@types/react-dom": "^17.0.11", - "@types/react-helmet": "^6.1.5", - "@types/react-lazylog": "^4.5.1", - "@types/react-paginate": "^7.1.1", - "@types/react-slick": "^0.23.10", - "@types/react-table": "^7.7.12", - "@types/react-widgets": "^4.4.7", - "@types/sanitize-html": "^2.6.2", - "@types/styled-components": "^5.1.25", - "@types/testing-library__jest-dom": "^5.14.5", - "@types/unist": "^2.0.5", - "@typescript-eslint/eslint-plugin": "^5.27.1", - "@typescript-eslint/parser": "^5.27.1", - "@vitejs/plugin-basic-ssl": "^1.0.1", - "@vitejs/plugin-react": "^3.0.1", - "babel-jest": "^29.3.1", - "chalk": "^4.1.2", - "dotenv": "^16.0.3", - "eslint": "^8.32.0", - "eslint-config-prettier": "^8.6.0", - "eslint-config-react-app": "^7.0.1", - "eslint-plugin-css-modules": "^2.11.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^26.5.3", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-unused-imports": "^2.0.0", - "express": "^4.18.1", - "history": "^5.3.0", - "husky": "^8.0.1", - "jest": "^29.3.0", - "jest-environment-jsdom": "^29.3.1", - "license-checker": "^25.0.1", - "lint-staged": "^12.3.7", - "meow": "^9.0.0", - "node-fetch": "^2.6.7", - "optionator": "^0.9.1", - "orval": "^6.11.1", - "prettier": "^2.6.2", - "react-select-event": "^5.5.0", - "storybook": "^7.0.0-beta.36", - "stylelint": "^14.9.1", - "stylelint-config-css-modules": "^4.1.0", - "stylelint-config-prettier-scss": "^0.0.1", - "stylelint-config-standard": "^26.0.0", - "stylelint-config-standard-scss": "^5.0.0", - "tar": "^6.1.11", - "timezone-mock": "^1.3.4", - "tmpl": "^1.0.5", - "ts-node": "^10.8.1", - "typescript": "^4.9.5", - "typescript-plugin-css-modules": "^4.1.1", - "vite": "^4.0.4", - "vite-plugin-checker": "^0.5.5", - "vite-plugin-svgr": "^2.4.0", - "vite-tsconfig-paths": "^4.0.3" - }, - "overrides": { - "minimatch": "^3.0.5" - }, - "lint-staged": { - "src/**/*.{js,jsx,ts,tsx}": [ - "eslint --fix" - ], - "src/**/*.{css,scss,md,json}": [ - "prettier --write" - ], - "{public,src}/**/*.{css,scss}": [ - "stylelint --fix" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "pnpm": { - "patchedDependencies": { - "react-virtualized@9.22.3": "patches/react-virtualized@9.22.3.patch" - }, - "overrides": { - "json5@<1.0.2": ">=1.0.2", - "postcss@<7.0.36": ">=7.0.36", - "loader-utils@<1.4.1": ">=1.4.1" - } - } -} diff --git a/airbyte-webapp/packages/README.md b/airbyte-webapp/packages/README.md deleted file mode 100644 index 5f39b4e15be9c..0000000000000 --- a/airbyte-webapp/packages/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This folder should only contain other folders that are treated like local npm packages, -e.g. because we want to provide plugins or configuration for build tools. \ No newline at end of file diff --git a/airbyte-webapp/packages/eslint-plugin/index.js b/airbyte-webapp/packages/eslint-plugin/index.js deleted file mode 100644 index e874928d7d49f..0000000000000 --- a/airbyte-webapp/packages/eslint-plugin/index.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - rules: { - "no-hardcoded-connector-ids": require("./no-hardcoded-connector-ids"), - }, - configs: { - recommended: { - rules: { - "@airbyte/no-hardcoded-connector-ids": "error", - }, - }, - }, -}; diff --git a/airbyte-webapp/packages/eslint-plugin/no-hardcoded-connector-ids.js b/airbyte-webapp/packages/eslint-plugin/no-hardcoded-connector-ids.js deleted file mode 100644 index e08f08e4bae98..0000000000000 --- a/airbyte-webapp/packages/eslint-plugin/no-hardcoded-connector-ids.js +++ /dev/null @@ -1,38 +0,0 @@ -const destinations = require("../../src/utils/connectors/destinations.json"); -const sources = require("../../src/utils/connectors/sources.json"); - -// Create a map for connector id to variable name (i.e. flip the direction of the map) -const sourceIdToName = Object.fromEntries(Object.entries(sources).map((entry) => [entry[1], entry[0]])); -const destinationIdToName = Object.fromEntries(Object.entries(destinations).map((entry) => [entry[1], entry[0]])); - -const validateStringContent = (context, node, nodeContent) => { - if (nodeContent in destinationIdToName) { - context.report({ node, messageId: "destinationId", data: { id: nodeContent, name: destinationIdToName[nodeContent] } }); - } else if (nodeContent in sourceIdToName) { - context.report({ node, messageId: "sourceId", data: { id: nodeContent, name: sourceIdToName[nodeContent] } }); - } -}; - -module.exports = { - meta: { - type: "suggestion", - messages: { - sourceId: "Found hard-coded connector id, use `ConnectorIds.Sources.{{ name }}` from `utils/connectors` instead.", - destinationId: - "Found hard-coded connector id, use `ConnectorIds.Destinations.{{ name }}` from `utils/connectors` instead.", - }, - }, - create: (context) => ({ - Literal: (node) => { - if (typeof node.value === "string") { - validateStringContent(context, node, node.value); - } - }, - TemplateLiteral: (node) => { - // Only check template literals which are "static", i.e. don't contain ${} elements - if (!node.expressions.length && node.quasis.length === 1) { - validateStringContent(context, node, node.quasis[0].value.raw); - } - }, - }), -}; diff --git a/airbyte-webapp/packages/stylelint-plugin/index.js b/airbyte-webapp/packages/stylelint-plugin/index.js deleted file mode 100644 index bafdf357ddf0b..0000000000000 --- a/airbyte-webapp/packages/stylelint-plugin/index.js +++ /dev/null @@ -1,12 +0,0 @@ -const stylelint = require("stylelint"); - -const rules = { - "no-color-variables-in-rgba": require("./no-color-variables-in-rgba"), - "no-use-renaming": require("./no-use-renaming"), -}; - -const rulesPlugins = Object.keys(rules).map((ruleName) => - stylelint.createPlugin(`airbyte/${ruleName}`, rules[ruleName]) -); - -module.exports = rulesPlugins; diff --git a/airbyte-webapp/packages/stylelint-plugin/no-color-variables-in-rgba.js b/airbyte-webapp/packages/stylelint-plugin/no-color-variables-in-rgba.js deleted file mode 100644 index 9f88d5bc950fb..0000000000000 --- a/airbyte-webapp/packages/stylelint-plugin/no-color-variables-in-rgba.js +++ /dev/null @@ -1,37 +0,0 @@ -const stylelint = require("stylelint"); -const { ruleMessages } = stylelint.utils; -const ruleName = "airbyte/no-color-variables-in-rgba"; -const messages = ruleMessages(ruleName, { - variableFoundInRgba: () => - `A color variable can't be used within an rgba() function. Explanation: ${LINK_TO_STYLEGUIDE}`, -}); -const LINK_TO_STYLEGUIDE = - "https://github.com/airbytehq/airbyte/blob/master/airbyte-webapp/STYLEGUIDE.md#color-variables-cannot-be-used-inside-of-rgba-functions"; - -module.exports.ruleName = ruleName; -module.exports.messages = messages; - -/** - * This stylelint rule checks if a color variable is used inside of rgba(), which we do not currently support. - * There are no options passed to the rule, as long as it is enabled in .stylelintrc it will be enforced. - */ -module.exports = (enabled) => { - return function lint(postcssRoot, postcssResult) { - if (!enabled) { - return () => null; - } - postcssRoot.walkDecls((decl) => { - // Check each value to see if it contains a string like "rgba(colors.$" or "rgba( ... colors.$" - const hasVariableInRgba = /rgba\([^)]*colors\.\$/.test(decl.value); - if (hasVariableInRgba) { - stylelint.utils.report({ - ruleName, - result: postcssResult, - message: messages.variableFoundInRgba(), - node: decl, - word: "blue", - }); - } - }); - }; -}; diff --git a/airbyte-webapp/packages/stylelint-plugin/no-use-renaming.js b/airbyte-webapp/packages/stylelint-plugin/no-use-renaming.js deleted file mode 100644 index 07d4604615985..0000000000000 --- a/airbyte-webapp/packages/stylelint-plugin/no-use-renaming.js +++ /dev/null @@ -1,33 +0,0 @@ -const stylelint = require("stylelint"); -const { ruleMessages } = stylelint.utils; -const ruleName = "airbyte/no-use-renaming"; -const messages = ruleMessages(ruleName, { - rejected: () => `You should not assign @use imports a different name.`, -}); - -module.exports.ruleName = ruleName; -module.exports.messages = messages; - -/** - * This stylelint rule checks a `@use` statement got a new name assigned e.g. `@use "scss/variables" as var` - * and fails if so. - */ -/** @type {import('stylelint').Rule} */ -module.exports = (enabled) => { - return function lint(postcssRoot, postcssResult) { - if (!enabled) { - return; - } - postcssRoot.walkAtRules((rule) => { - if (rule.name === "use" && rule.params.includes(" as ")) { - stylelint.utils.report({ - ruleName, - node: rule, - message: messages.rejected(), - result: postcssResult, - word: `as `, - }); - } - }); - }; -}; diff --git a/airbyte-webapp/packages/vite-plugins/build-info.ts b/airbyte-webapp/packages/vite-plugins/build-info.ts deleted file mode 100644 index 44e31c1051286..0000000000000 --- a/airbyte-webapp/packages/vite-plugins/build-info.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Plugin } from "vite"; - -import fs from "fs"; -import path from "path"; - -import { v4 as uuidV4 } from "uuid"; - -const buildHash = uuidV4(); - -/** - * A Vite plugin that will generate on every build a new random UUID and write that to the `/buildInfo.json` - * file as well as make it available as `process.env.BUILD_HASH` in code. - */ -export function buildInfo(): Plugin { - return { - name: "airbyte/build-info", - buildStart() { - fs.writeFileSync(path.resolve(__dirname, "../../public/buildInfo.json"), JSON.stringify({ build: buildHash })); - }, - config: () => ({ - define: { - "process.env.BUILD_HASH": JSON.stringify(buildHash), - }, - }), - }; -} diff --git a/airbyte-webapp/packages/vite-plugins/doc-middleware.ts b/airbyte-webapp/packages/vite-plugins/doc-middleware.ts deleted file mode 100644 index 15ea716b37a0e..0000000000000 --- a/airbyte-webapp/packages/vite-plugins/doc-middleware.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Connect, Plugin } from "vite"; - -import express from "express"; - -export function docMiddleware(): Plugin { - return { - name: "airbyte/doc-middleware", - configureServer(server) { - // Serve the docs used in the sidebar. During building Gradle will copy those into the docker image - // Relavant gradle task :airbyte-webapp:copyDocs - server.middlewares.use( - "/docs/integrations", - express.static(`${__dirname}/../../../docs/integrations`) as Connect.NextHandleFunction - ); - // workaround for adblockers to serve google ads docs in development - server.middlewares.use( - "/docs/integrations/sources/gglad.md", - express.static(`${__dirname}/../../../docs/integrations/sources/google-ads.md`) as Connect.NextHandleFunction - ); - // Server assets that can be used during. Related gradle task: :airbyte-webapp:copyDocAssets - server.middlewares.use( - "/docs/.gitbook", - express.static(`${__dirname}/../../../docs/.gitbook`) as Connect.NextHandleFunction - ); - }, - }; -} diff --git a/airbyte-webapp/packages/vite-plugins/index.ts b/airbyte-webapp/packages/vite-plugins/index.ts deleted file mode 100644 index 6dd7972862575..0000000000000 --- a/airbyte-webapp/packages/vite-plugins/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { docMiddleware } from "./doc-middleware"; -export { buildInfo } from "./build-info"; diff --git a/airbyte-webapp/patches/react-virtualized@9.22.3.patch b/airbyte-webapp/patches/react-virtualized@9.22.3.patch deleted file mode 100644 index 598ac4eb7beb5..0000000000000 --- a/airbyte-webapp/patches/react-virtualized@9.22.3.patch +++ /dev/null @@ -1,10 +0,0 @@ -diff --git a/dist/es/WindowScroller/utils/onScroll.js b/dist/es/WindowScroller/utils/onScroll.js -index d00f0f18c6596e4e57f4f762f91fed4282610c91..c8496e8eabafdf9cf6071986ec446839d7b65556 100644 ---- a/dist/es/WindowScroller/utils/onScroll.js -+++ b/dist/es/WindowScroller/utils/onScroll.js -@@ -71,4 +71,3 @@ export function unregisterScrollListener(component, element) { - } - } - } -\ No newline at end of file --import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js"; \ No newline at end of file diff --git a/airbyte-webapp/pnpm-lock.yaml b/airbyte-webapp/pnpm-lock.yaml deleted file mode 100644 index 2e4aa5b74d4c2..0000000000000 --- a/airbyte-webapp/pnpm-lock.yaml +++ /dev/null @@ -1,16033 +0,0 @@ -lockfileVersion: 5.4 - -overrides: - json5@<1.0.2: '>=1.0.2' - postcss@<7.0.36: '>=7.0.36' - loader-utils@<1.4.1: '>=1.4.1' - -patchedDependencies: - react-virtualized@9.22.3: - hash: wem7zdhrj6jola7ic3qcehiqii - path: patches/react-virtualized@9.22.3.patch - -specifiers: - '@airbyte/eslint-plugin': link:packages/eslint-plugin - '@babel/core': ^7.20.12 - '@babel/preset-env': ^7.20.2 - '@babel/preset-react': ^7.18.6 - '@babel/preset-typescript': ^7.18.6 - '@datadog/browser-rum': ^4.21.2 - '@floating-ui/react-dom': ^1.0.0 - '@fortawesome/fontawesome-svg-core': ^6.1.1 - '@fortawesome/free-brands-svg-icons': ^6.1.1 - '@fortawesome/free-regular-svg-icons': ^6.1.1 - '@fortawesome/free-solid-svg-icons': ^6.1.1 - '@fortawesome/react-fontawesome': ^0.1.18 - '@headlessui/react': ^1.6.5 - '@monaco-editor/react': ^4.4.5 - '@sentry/react': ^6.19.6 - '@sentry/tracing': ^6.19.6 - '@storybook/addon-actions': ^7.0.0-beta.36 - '@storybook/addon-essentials': ^7.0.0-beta.36 - '@storybook/addon-links': ^7.0.0-beta.36 - '@storybook/react': ^7.0.0-beta.36 - '@storybook/react-vite': ^7.0.0-beta.36 - '@storybook/theming': ^7.0.0-beta.36 - '@tanstack/react-table': ^8.7.0 - '@testing-library/jest-dom': ^5.16.4 - '@testing-library/react': ^12.1.3 - '@testing-library/react-hooks': ^7.0.2 - '@testing-library/user-event': ^13.5.0 - '@types/diff': ^5.0.2 - '@types/flat': ^5.0.2 - '@types/jest': ^27.5.2 - '@types/js-yaml': ^4.0.5 - '@types/json-schema': ^7.0.11 - '@types/lodash': ^4.14.182 - '@types/node': ^17.0.40 - '@types/node-fetch': ^2.6.2 - '@types/react': ^17.0.39 - '@types/react-datepicker': ^4.8.0 - '@types/react-dom': ^17.0.11 - '@types/react-helmet': ^6.1.5 - '@types/react-lazylog': ^4.5.1 - '@types/react-paginate': ^7.1.1 - '@types/react-slick': ^0.23.10 - '@types/react-table': ^7.7.12 - '@types/react-widgets': ^4.4.7 - '@types/sanitize-html': ^2.6.2 - '@types/segment-analytics': ^0.0.34 - '@types/styled-components': ^5.1.25 - '@types/testing-library__jest-dom': ^5.14.5 - '@types/unist': ^2.0.5 - '@types/uuid': ^9.0.0 - '@typescript-eslint/eslint-plugin': ^5.27.1 - '@typescript-eslint/parser': ^5.27.1 - '@vitejs/plugin-basic-ssl': ^1.0.1 - '@vitejs/plugin-react': ^3.0.1 - babel-jest: ^29.3.1 - chalk: ^4.1.2 - classnames: ^2.3.1 - date-fns: ^2.29.3 - dayjs: ^1.11.3 - diff: ^5.1.0 - dotenv: ^16.0.3 - eslint: ^8.32.0 - eslint-config-prettier: ^8.6.0 - eslint-config-react-app: ^7.0.1 - eslint-plugin-css-modules: ^2.11.0 - eslint-plugin-import: ^2.27.5 - eslint-plugin-jest: ^26.5.3 - eslint-plugin-jsx-a11y: ^6.7.1 - eslint-plugin-prettier: ^4.2.1 - eslint-plugin-unused-imports: ^2.0.0 - express: ^4.18.1 - firebase: ^9.8.2 - flat: ^5.0.2 - formik: ^2.2.9 - framer-motion: ^6.3.11 - history: ^5.3.0 - husky: ^8.0.1 - jest: ^29.3.0 - jest-environment-jsdom: ^29.3.1 - js-yaml: ^4.1.0 - json-schema: ^0.4.0 - launchdarkly-js-client-sdk: ^3.1.0 - license-checker: ^25.0.1 - lint-staged: ^12.3.7 - lodash: ^4.17.21 - meow: ^9.0.0 - monaco-editor: ^0.34.1 - node-fetch: ^2.6.7 - optionator: ^0.9.1 - orval: ^6.11.1 - prettier: ^2.6.2 - query-string: ^6.13.1 - react: ^17.0.2 - react-datepicker: ^4.8.0 - react-dom: ^17.0.2 - react-helmet-async: ^1.3.0 - react-intersection-observer: ^9.4.2 - react-intl: ^6.1.1 - react-lazylog: ^4.5.3 - react-markdown: ^7.0.1 - react-paginate: ^8.1.3 - react-query: ^3.39.1 - react-reflex: ^4.0.9 - react-resize-detector: ^8.0.3 - react-router-dom: 6.3.0 - react-select: ^5.4.0 - react-select-event: ^5.5.0 - react-slick: ^0.29.0 - react-table: ^7.8.0 - react-use: ^17.4.0 - react-use-intercom: ^1.5.2 - react-widgets: ^4.6.1 - recharts: ^2.1.13 - rehype-slug: ^5.0.1 - rehype-urls: ^1.1.1 - remark-directive: ^2.0.1 - remark-frontmatter: ^4.0.1 - remark-gfm: ^3.0.0 - rxjs: ^7.5.5 - sanitize-html: ^2.7.1 - sass: ^1.52.2 - storybook: ^7.0.0-beta.36 - styled-components: ^5.3.5 - stylelint: ^14.9.1 - stylelint-config-css-modules: ^4.1.0 - stylelint-config-prettier-scss: ^0.0.1 - stylelint-config-standard: ^26.0.0 - stylelint-config-standard-scss: ^5.0.0 - tar: ^6.1.11 - timezone-mock: ^1.3.4 - tmpl: ^1.0.5 - ts-node: ^10.8.1 - typesafe-actions: ^5.1.0 - typescript: ^4.9.5 - typescript-plugin-css-modules: ^4.1.1 - unified: ^10.1.2 - unist-util-visit: ^4.1.0 - url: ^0.11.0 - uuid: ^9.0.0 - vite: ^4.0.4 - vite-plugin-checker: ^0.5.5 - vite-plugin-svgr: ^2.4.0 - vite-tsconfig-paths: ^4.0.3 - yup: ^0.32.11 - -dependencies: - '@datadog/browser-rum': 4.30.1 - '@floating-ui/react-dom': 1.2.1_sfoxds7t5ydpegc3knd667wn6m - '@fortawesome/fontawesome-svg-core': 6.2.1 - '@fortawesome/free-brands-svg-icons': 6.2.1 - '@fortawesome/free-regular-svg-icons': 6.2.1 - '@fortawesome/free-solid-svg-icons': 6.2.1 - '@fortawesome/react-fontawesome': 0.1.19_chs37cqfjyeefvqfxhgbgy2rma - '@headlessui/react': 1.7.7_sfoxds7t5ydpegc3knd667wn6m - '@monaco-editor/react': 4.4.6_5rrpgbvkp3saaogcekwkrw2jia - '@sentry/react': 6.19.7_react@17.0.2 - '@sentry/tracing': 6.19.7 - '@tanstack/react-table': 8.7.6_sfoxds7t5ydpegc3knd667wn6m - '@types/diff': 5.0.2 - '@types/node-fetch': 2.6.2 - '@types/segment-analytics': 0.0.34 - '@types/uuid': 9.0.0 - classnames: 2.3.2 - date-fns: 2.29.3 - dayjs: 1.11.7 - diff: 5.1.0 - firebase: 9.15.0 - flat: 5.0.2 - formik: 2.2.9_react@17.0.2 - framer-motion: 6.5.1_sfoxds7t5ydpegc3knd667wn6m - js-yaml: 4.1.0 - json-schema: 0.4.0 - launchdarkly-js-client-sdk: 3.1.0 - lodash: 4.17.21 - monaco-editor: 0.34.1 - query-string: 6.14.1 - react: 17.0.2 - react-datepicker: 4.8.0_sfoxds7t5ydpegc3knd667wn6m - react-dom: 17.0.2_react@17.0.2 - react-helmet-async: 1.3.0_sfoxds7t5ydpegc3knd667wn6m - react-intersection-observer: 9.4.2_react@17.0.2 - react-intl: 6.2.5_oatgdhaahtizs2uezdzbohxvne - react-lazylog: 4.5.3_sfoxds7t5ydpegc3knd667wn6m - react-markdown: 7.1.2_q5o373oqrklnndq2vhekyuzhxi - react-paginate: 8.1.4_react@17.0.2 - react-query: 3.39.2_sfoxds7t5ydpegc3knd667wn6m - react-reflex: 4.0.9_sfoxds7t5ydpegc3knd667wn6m - react-resize-detector: 8.0.3_sfoxds7t5ydpegc3knd667wn6m - react-router-dom: 6.3.0_sfoxds7t5ydpegc3knd667wn6m - react-select: 5.7.0_dlps62spiehie4hvtd46aaye5u - react-slick: 0.29.0_sfoxds7t5ydpegc3knd667wn6m - react-table: 7.8.0_react@17.0.2 - react-use: 17.4.0_sfoxds7t5ydpegc3knd667wn6m - react-use-intercom: 1.5.2_sfoxds7t5ydpegc3knd667wn6m - react-widgets: 4.6.1_sfoxds7t5ydpegc3knd667wn6m - recharts: 2.3.2_sfoxds7t5ydpegc3knd667wn6m - rehype-slug: 5.1.0 - rehype-urls: 1.1.1 - remark-directive: 2.0.1 - remark-frontmatter: 4.0.1 - remark-gfm: 3.0.1 - rxjs: 7.8.0 - sanitize-html: 2.8.1 - sass: 1.57.1 - styled-components: 5.3.6_sfoxds7t5ydpegc3knd667wn6m - typesafe-actions: 5.1.0 - unified: 10.1.2 - unist-util-visit: 4.1.1 - url: 0.11.0 - uuid: 9.0.0 - yup: 0.32.11 - -devDependencies: - '@airbyte/eslint-plugin': link:packages/eslint-plugin - '@babel/core': 7.20.12 - '@babel/preset-env': 7.20.2_@babel+core@7.20.12 - '@babel/preset-react': 7.18.6_@babel+core@7.20.12 - '@babel/preset-typescript': 7.18.6_@babel+core@7.20.12 - '@storybook/addon-actions': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-essentials': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-links': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/react': 7.0.0-beta.38_jgxnvbe4faw3ohf4h6p42qq6oy - '@storybook/react-vite': 7.0.0-beta.38_ixkwjuwc6whfuuxbuybnyjw2h4 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@testing-library/jest-dom': 5.16.5 - '@testing-library/react': 12.1.5_sfoxds7t5ydpegc3knd667wn6m - '@testing-library/react-hooks': 7.0.2_sfoxds7t5ydpegc3knd667wn6m - '@testing-library/user-event': 13.5.0 - '@types/flat': 5.0.2 - '@types/jest': 27.5.2 - '@types/js-yaml': 4.0.5 - '@types/json-schema': 7.0.11 - '@types/lodash': 4.14.191 - '@types/node': 17.0.45 - '@types/react': 17.0.52 - '@types/react-datepicker': 4.8.0_sfoxds7t5ydpegc3knd667wn6m - '@types/react-dom': 17.0.18 - '@types/react-helmet': 6.1.6 - '@types/react-lazylog': 4.5.1 - '@types/react-paginate': 7.1.1 - '@types/react-slick': 0.23.10 - '@types/react-table': 7.7.14 - '@types/react-widgets': 4.4.7 - '@types/sanitize-html': 2.8.0 - '@types/styled-components': 5.1.26 - '@types/testing-library__jest-dom': 5.14.5 - '@types/unist': 2.0.6 - '@typescript-eslint/eslint-plugin': 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy - '@typescript-eslint/parser': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - '@vitejs/plugin-basic-ssl': 1.0.1_vite@4.0.4 - '@vitejs/plugin-react': 3.0.1_vite@4.0.4 - babel-jest: 29.3.1_@babel+core@7.20.12 - chalk: 4.1.2 - dotenv: 16.0.3 - eslint: 8.32.0 - eslint-config-prettier: 8.6.0_eslint@8.32.0 - eslint-config-react-app: 7.0.1_f3p7cdzsbkhsmnshbzhbbdgmve - eslint-plugin-css-modules: 2.11.0_eslint@8.32.0 - eslint-plugin-import: 2.27.5_2l6piu6guil2f63lj3qmhzbnn4 - eslint-plugin-jest: 26.9.0_i5clxtuiaceouxhg5syqkw5wwi - eslint-plugin-jsx-a11y: 6.7.1_eslint@8.32.0 - eslint-plugin-prettier: 4.2.1_cn4lalcyadplruoxa5mhp7j3dq - eslint-plugin-unused-imports: 2.0.0_virssgr5omih4ylyae2gddvmxu - express: 4.18.2 - history: 5.3.0 - husky: 8.0.3 - jest: 29.3.1_2263m44mchjafa7bz7l52hbcpa - jest-environment-jsdom: 29.3.1 - license-checker: 25.0.1 - lint-staged: 12.5.0 - meow: 9.0.0 - node-fetch: 2.6.8 - optionator: 0.9.1 - orval: 6.11.1_typescript@4.9.5 - prettier: 2.8.3 - react-select-event: 5.5.1 - storybook: 7.0.0-beta.38 - stylelint: 14.16.1 - stylelint-config-css-modules: 4.1.0_stylelint@14.16.1 - stylelint-config-prettier-scss: 0.0.1_stylelint@14.16.1 - stylelint-config-standard: 26.0.0_stylelint@14.16.1 - stylelint-config-standard-scss: 5.0.0_stylelint@14.16.1 - tar: 6.1.13 - timezone-mock: 1.3.6 - tmpl: 1.0.5 - ts-node: 10.9.1_cin3sed6ohfsopbmt6orxeb4o4 - typescript: 4.9.5 - typescript-plugin-css-modules: 4.1.1_6qtx7vkbdhwvdm4crzlegk4mvi - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - vite-plugin-checker: 0.5.5_svpeoejlom624h637oo4yy72dy - vite-plugin-svgr: 2.4.0_vite@4.0.4 - vite-tsconfig-paths: 4.0.5_typescript@4.9.5 - -packages: - - /@adobe/css-tools/4.0.2: - resolution: {integrity: sha512-Fx6tYjk2wKUgLi8uMANZr8GNZx05u44ArIJldn9VxLvolzlJVgHbTUCbwhMd6bcYky178+WUSxPHO3DAtGLWpw==} - dev: true - - /@ampproject/remapping/2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.17 - - /@apidevtools/json-schema-ref-parser/9.0.6: - resolution: {integrity: sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==} - dependencies: - '@jsdevtools/ono': 7.1.3 - call-me-maybe: 1.0.2 - js-yaml: 3.14.1 - dev: true - - /@apidevtools/openapi-schemas/2.1.0: - resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} - engines: {node: '>=10'} - dev: true - - /@apidevtools/swagger-methods/3.0.2: - resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==} - dev: true - - /@apidevtools/swagger-parser/10.1.0: - resolution: {integrity: sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==} - peerDependencies: - openapi-types: '>=7' - dependencies: - '@apidevtools/json-schema-ref-parser': 9.0.6 - '@apidevtools/openapi-schemas': 2.1.0 - '@apidevtools/swagger-methods': 3.0.2 - '@jsdevtools/ono': 7.1.3 - ajv: 8.12.0 - ajv-draft-04: 1.0.0_ajv@8.12.0 - call-me-maybe: 1.0.2 - dev: true - - /@asyncapi/specs/3.2.1: - resolution: {integrity: sha512-FO+EteK+Gk3zwumrBw6frpp9cJ4oQL5++hBBpfM81w16e9KaiA4sKrzvQsvVjifoZZHNvVEX4D2zoz9i8CLccQ==} - dev: true - - /@aw-web-design/x-default-browser/1.4.88: - resolution: {integrity: sha512-AkEmF0wcwYC2QkhK703Y83fxWARttIWXDmQN8+cof8FmFZ5BRhnNXGymeb1S73bOCLfWjYELxtujL56idCN/XA==} - hasBin: true - dependencies: - default-browser-id: 3.0.0 - dev: true - - /@babel/code-frame/7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - - /@babel/compat-data/7.20.10: - resolution: {integrity: sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==} - engines: {node: '>=6.9.0'} - - /@babel/core/7.20.12: - resolution: {integrity: sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.7 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12 - '@babel/helper-module-transforms': 7.20.11 - '@babel/helpers': 7.20.7 - '@babel/parser': 7.20.7 - '@babel/template': 7.20.7 - '@babel/traverse': 7.20.12 - '@babel/types': 7.20.7 - convert-source-map: 1.9.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - - /@babel/eslint-parser/7.19.1_2je5tsgpdnpnp4f5qs5fqust6m: - resolution: {integrity: sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': '>=7.11.0' - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.20.12 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.32.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.0 - dev: true - - /@babel/generator/7.20.7: - resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - - /@babel/helper-annotate-as-pure/7.18.6: - resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - - /@babel/helper-builder-binary-assignment-operator-visitor/7.18.9: - resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-explode-assignable-expression': 7.18.6 - '@babel/types': 7.20.7 - dev: true - - /@babel/helper-compilation-targets/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.20.10 - '@babel/core': 7.20.12 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - lru-cache: 5.1.1 - semver: 6.3.0 - - /@babel/helper-create-class-features-plugin/7.20.12_@babel+core@7.20.12: - resolution: {integrity: sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@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-skip-transparent-expression-wrappers': 7.20.0 - '@babel/helper-split-export-declaration': 7.18.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-create-regexp-features-plugin/7.20.5_@babel+core@7.20.12: - resolution: {integrity: sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.18.6 - regexpu-core: 5.2.2 - dev: true - - /@babel/helper-define-polyfill-provider/0.3.3_@babel+core@7.20.12: - resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} - peerDependencies: - '@babel/core': ^7.4.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.1 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-environment-visitor/7.18.9: - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} - - /@babel/helper-explode-assignable-expression/7.18.6: - resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - dev: true - - /@babel/helper-function-name/7.19.0: - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/types': 7.20.7 - - /@babel/helper-hoist-variables/7.18.6: - resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - - /@babel/helper-member-expression-to-functions/7.20.7: - resolution: {integrity: sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - dev: true - - /@babel/helper-module-imports/7.18.6: - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - - /@babel/helper-module-transforms/7.20.11: - resolution: {integrity: sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==} - engines: {node: '>=6.9.0'} - 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.12 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - - /@babel/helper-optimise-call-expression/7.18.6: - resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - dev: true - - /@babel/helper-plugin-utils/7.20.2: - resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} - engines: {node: '>=6.9.0'} - - /@babel/helper-remap-async-to-generator/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-wrap-function': 7.20.5 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-replace-supers/7.20.7: - resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} - engines: {node: '>=6.9.0'} - 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.12 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-simple-access/7.20.2: - resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - - /@babel/helper-skip-transparent-expression-wrappers/7.20.0: - resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - dev: true - - /@babel/helper-split-export-declaration/7.18.6: - resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - - /@babel/helper-string-parser/7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier/7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option/7.18.6: - resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} - engines: {node: '>=6.9.0'} - - /@babel/helper-wrap-function/7.20.5: - resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.19.0 - '@babel/template': 7.20.7 - '@babel/traverse': 7.20.12 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helpers/7.20.7: - resolution: {integrity: sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/traverse': 7.20.12 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - - /@babel/highlight/7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - - /@babel/parser/7.20.7: - resolution: {integrity: sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.20.7 - - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.20.12 - '@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+core@7.20.12 - dev: true - - /@babel/plugin-proposal-async-generator-functions/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-class-static-block/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-decorators/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-JB45hbUweYpwAGjkiM7uCyXMENH2lG+9r3G2E+ttc2PRXAoEkpfd/KW5jDg4j8RS6tLtTG1jZi9LbHZVSfs1/A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/plugin-syntax-decorators': 7.19.0_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-dynamic-import/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-logical-assignment-operators/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-numeric-separator/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-object-rest-spread/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.20.10 - '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-transform-parameters': 7.20.7_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.20.12 - dev: true - - /@babel/plugin-proposal-optional-chaining/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@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+core@7.20.12 - dev: true - - /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-private-property-in-object/7.20.5_@babel+core@7.20.12: - resolution: {integrity: sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} - engines: {node: '>=4'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.20.5_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.20.12: - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.20.12: - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.20.12: - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-decorators/7.19.0_@babel+core@7.20.12: - resolution: {integrity: sha512-xaBZUEDntt4faL1yN8oIFlhfXeQAWJW7CLKYsHTUqriCUbj8xOra8bfxxKGi/UwExPFBuPdH4XfHc9rGQhrVkQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-flow/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-import-assertions/7.20.0_@babel+core@7.20.12: - resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.20.12: - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.20.12: - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.20.12: - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.20.12: - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.20.12: - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.20.12: - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-typescript/7.20.0_@babel+core@7.20.12: - resolution: {integrity: sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-arrow-functions/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-async-to-generator/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-block-scoped-functions/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-block-scoping/7.20.11_@babel+core@7.20.12: - resolution: {integrity: sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-classes/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12 - '@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 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-computed-properties/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/template': 7.20.7 - dev: true - - /@babel/plugin-transform-destructuring/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-dotall-regex/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.20.5_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-duplicate-keys/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-exponentiation-operator/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-flow-strip-types/7.19.0_@babel+core@7.20.12: - resolution: {integrity: sha512-sgeMlNaQVbCSpgLSKP4ZZKfsJVnFnNQlUSk6gPYzR/q7tzCgQF2t8RBKAP6cKJeZdveei7Q7Jm527xepI8lNLg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-flow': 7.18.6_@babel+core@7.20.12 - dev: true - - /@babel/plugin-transform-for-of/7.18.8_@babel+core@7.20.12: - resolution: {integrity: sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-function-name/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-literals/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-member-expression-literals/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-modules-amd/7.20.11_@babel+core@7.20.12: - resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.20.11 - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-commonjs/7.20.11_@babel+core@7.20.12: - resolution: {integrity: sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.20.11 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-simple-access': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-systemjs/7.20.11_@babel+core@7.20.12: - resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@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 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-umd/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.20.11 - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-named-capturing-groups-regex/7.20.5_@babel+core@7.20.12: - resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.20.5_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-new-target/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-object-super/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-replace-supers': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-parameters/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-property-literals/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-react-display-name/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/plugin-transform-react-jsx': 7.20.7_@babel+core@7.20.12 - dev: true - - /@babel/plugin-transform-react-jsx-self/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-react-jsx-source/7.19.6_@babel+core@7.20.12: - resolution: {integrity: sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-react-jsx/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-Tfq7qqD+tRj3EoDhY00nn2uP2hsRxgYGi5mLQ5TimKav0a9Lrpd4deE+fcLXU8zFYRjlKPHZhpCvfEA6qnBxqQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@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+core@7.20.12 - '@babel/types': 7.20.7 - dev: true - - /@babel/plugin-transform-react-pure-annotations/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-regenerator/7.20.5_@babel+core@7.20.12: - resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - regenerator-transform: 0.15.1 - dev: true - - /@babel/plugin-transform-reserved-words/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-runtime/7.19.6_@babel+core@7.20.12: - resolution: {integrity: sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-plugin-utils': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.12 - babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.12 - babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.12 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-shorthand-properties/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-spread/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - dev: true - - /@babel/plugin-transform-sticky-regex/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-template-literals/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-typeof-symbol/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-typescript/7.20.7_@babel+core@7.20.12: - resolution: {integrity: sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.20.12_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-unicode-escapes/7.18.10_@babel+core@7.20.12: - resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-unicode-regex/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.20.5_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/preset-env/7.20.2_@babel+core@7.20.12: - resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.20.10 - '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.12 - '@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+core@7.20.12 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-async-generator-functions': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-class-static-block': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-dynamic-import': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-export-namespace-from': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-proposal-json-strings': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-logical-assignment-operators': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-numeric-separator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-object-rest-spread': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-optional-catch-binding': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-optional-chaining': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-private-property-in-object': 7.20.5_@babel+core@7.20.12 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.12 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.20.12 - '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.12 - '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-import-assertions': 7.20.0_@babel+core@7.20.12 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.12 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.20.12 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.12 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.12 - '@babel/plugin-transform-arrow-functions': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-async-to-generator': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-block-scoped-functions': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-block-scoping': 7.20.11_@babel+core@7.20.12 - '@babel/plugin-transform-classes': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-computed-properties': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-destructuring': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-duplicate-keys': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-exponentiation-operator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-for-of': 7.18.8_@babel+core@7.20.12 - '@babel/plugin-transform-function-name': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-literals': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-member-expression-literals': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-modules-amd': 7.20.11_@babel+core@7.20.12 - '@babel/plugin-transform-modules-commonjs': 7.20.11_@babel+core@7.20.12 - '@babel/plugin-transform-modules-systemjs': 7.20.11_@babel+core@7.20.12 - '@babel/plugin-transform-modules-umd': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5_@babel+core@7.20.12 - '@babel/plugin-transform-new-target': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-object-super': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-parameters': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-property-literals': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-regenerator': 7.20.5_@babel+core@7.20.12 - '@babel/plugin-transform-reserved-words': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-shorthand-properties': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-spread': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-sticky-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-template-literals': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-typeof-symbol': 7.18.9_@babel+core@7.20.12 - '@babel/plugin-transform-unicode-escapes': 7.18.10_@babel+core@7.20.12 - '@babel/plugin-transform-unicode-regex': 7.18.6_@babel+core@7.20.12 - '@babel/preset-modules': 0.1.5_@babel+core@7.20.12 - '@babel/types': 7.20.7 - babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.12 - babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.12 - babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.12 - core-js-compat: 3.27.1 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/preset-flow/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-flow-strip-types': 7.19.0_@babel+core@7.20.12 - dev: true - - /@babel/preset-modules/0.1.5_@babel+core@7.20.12: - resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-dotall-regex': 7.18.6_@babel+core@7.20.12 - '@babel/types': 7.20.7 - esutils: 2.0.3 - dev: true - - /@babel/preset-react/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-react-display-name': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-jsx': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-pure-annotations': 7.18.6_@babel+core@7.20.12 - dev: true - - /@babel/preset-typescript/7.18.6_@babel+core@7.20.12: - resolution: {integrity: sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.18.6 - '@babel/plugin-transform-typescript': 7.20.7_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/register/7.18.9_@babel+core@7.20.12: - resolution: {integrity: sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - clone-deep: 4.0.1 - find-cache-dir: 2.1.0 - make-dir: 2.1.0 - pirates: 4.0.5 - source-map-support: 0.5.21 - dev: true - - /@babel/runtime/7.20.7: - resolution: {integrity: sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.13.11 - - /@babel/template/7.20.7: - resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.20.7 - '@babel/types': 7.20.7 - - /@babel/traverse/7.20.12: - resolution: {integrity: sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==} - engines: {node: '>=6.9.0'} - 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 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - /@babel/traverse/7.20.12_supports-color@5.5.0: - resolution: {integrity: sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==} - engines: {node: '>=6.9.0'} - 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 - debug: 4.3.4_supports-color@5.5.0 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/types/7.20.7: - resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - - /@base2/pretty-print-object/1.0.1: - resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==} - dev: true - - /@bcoe/v8-coverage/0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - - /@colors/colors/1.5.0: - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - requiresBuild: true - dev: true - optional: true - - /@cspotcode/source-map-support/0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@csstools/selector-specificity/2.0.2_wajs5nedgkikc5pcuwett7legi: - resolution: {integrity: sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==} - engines: {node: ^12 || ^14 || >=16} - peerDependencies: - postcss: ^8.2 - postcss-selector-parser: ^6.0.10 - dependencies: - postcss: 8.4.21 - postcss-selector-parser: 6.0.11 - dev: true - - /@datadog/browser-core/4.30.1: - resolution: {integrity: sha512-f2ETFJgZTHH3gzAKNEy8wI22Ae9jFtMk6t7s1QIyHwdFsftC0E0GKuCdMv2maeKMm/z8UYvP27vvGgXjbW1twg==} - dev: false - - /@datadog/browser-rum-core/4.30.1: - resolution: {integrity: sha512-scWb9zAJfIEQexabQxdm98wxy9CJzhqvsDX/5/DUyv1lQDAsjaP6IHWAMTkikHeHift67/E9j5FVTrUMaanydQ==} - dependencies: - '@datadog/browser-core': 4.30.1 - dev: false - - /@datadog/browser-rum/4.30.1: - resolution: {integrity: sha512-iOJJYjyS9j1EsD93RIwabqCPRpfDd7FrltbgVVll+4oJ+eE2lfO/wPWbLuV1Kr4jZ39tGSzef7GC/Q/dcNLYzQ==} - peerDependencies: - '@datadog/browser-logs': 4.30.1 - peerDependenciesMeta: - '@datadog/browser-logs': - optional: true - dependencies: - '@datadog/browser-core': 4.30.1 - '@datadog/browser-rum-core': 4.30.1 - dev: false - - /@discoveryjs/json-ext/0.5.7: - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} - dev: true - - /@emotion/babel-plugin/11.10.5_@babel+core@7.20.12: - resolution: {integrity: sha512-xE7/hyLHJac7D2Ve9dKroBBZqBT7WuPQmWcq7HSGb84sUuP4mlOWoB8dvVfD9yk5DHkU1m6RW7xSoDtnQHNQeA==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.18.6 - '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.12 - '@babel/runtime': 7.20.7 - '@emotion/hash': 0.9.0 - '@emotion/memoize': 0.8.0 - '@emotion/serialize': 1.1.1 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.1.3 - dev: false - - /@emotion/cache/11.10.5: - resolution: {integrity: sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==} - dependencies: - '@emotion/memoize': 0.8.0 - '@emotion/sheet': 1.2.1 - '@emotion/utils': 1.2.0 - '@emotion/weak-memoize': 0.3.0 - stylis: 4.1.3 - dev: false - - /@emotion/hash/0.9.0: - resolution: {integrity: sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==} - dev: false - - /@emotion/is-prop-valid/0.8.8: - resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} - requiresBuild: true - dependencies: - '@emotion/memoize': 0.7.4 - dev: false - optional: true - - /@emotion/is-prop-valid/1.2.0: - resolution: {integrity: sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==} - dependencies: - '@emotion/memoize': 0.8.0 - dev: false - - /@emotion/memoize/0.7.4: - resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} - dev: false - optional: true - - /@emotion/memoize/0.8.0: - resolution: {integrity: sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==} - dev: false - - /@emotion/react/11.10.5_nehdyrcubdy45i2h35h56gfg7i: - resolution: {integrity: sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A==} - peerDependencies: - '@babel/core': ^7.0.0 - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@babel/core': - optional: true - '@types/react': - optional: true - dependencies: - '@babel/core': 7.20.12 - '@babel/runtime': 7.20.7 - '@emotion/babel-plugin': 11.10.5_@babel+core@7.20.12 - '@emotion/cache': 11.10.5 - '@emotion/serialize': 1.1.1 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.0_react@17.0.2 - '@emotion/utils': 1.2.0 - '@emotion/weak-memoize': 0.3.0 - '@types/react': 17.0.52 - hoist-non-react-statics: 3.3.2 - react: 17.0.2 - dev: false - - /@emotion/serialize/1.1.1: - resolution: {integrity: sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==} - dependencies: - '@emotion/hash': 0.9.0 - '@emotion/memoize': 0.8.0 - '@emotion/unitless': 0.8.0 - '@emotion/utils': 1.2.0 - csstype: 3.1.1 - dev: false - - /@emotion/sheet/1.2.1: - resolution: {integrity: sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==} - dev: false - - /@emotion/stylis/0.8.5: - resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} - dev: false - - /@emotion/unitless/0.7.5: - resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} - dev: false - - /@emotion/unitless/0.8.0: - resolution: {integrity: sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==} - dev: false - - /@emotion/use-insertion-effect-with-fallbacks/1.0.0_react@17.0.2: - resolution: {integrity: sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==} - peerDependencies: - react: '>=16.8.0' - dependencies: - react: 17.0.2 - - /@emotion/utils/1.2.0: - resolution: {integrity: sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==} - dev: false - - /@emotion/weak-memoize/0.3.0: - resolution: {integrity: sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==} - dev: false - - /@esbuild/android-arm/0.15.18: - resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm/0.16.17: - resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-arm64/0.16.17: - resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64/0.16.17: - resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-arm64/0.16.17: - resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/darwin-x64/0.16.17: - resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-arm64/0.16.17: - resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/freebsd-x64/0.16.17: - resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm/0.16.17: - resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-arm64/0.16.17: - resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32/0.16.17: - resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64/0.15.18: - resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-loong64/0.16.17: - resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-mips64el/0.16.17: - resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ppc64/0.16.17: - resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-riscv64/0.16.17: - resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-s390x/0.16.17: - resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-x64/0.16.17: - resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/netbsd-x64/0.16.17: - resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/openbsd-x64/0.16.17: - resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /@esbuild/sunos-x64/0.16.17: - resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-arm64/0.16.17: - resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-ia32/0.16.17: - resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@esbuild/win32-x64/0.16.17: - resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@eslint/eslintrc/1.4.1: - resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.4.1 - globals: 13.19.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@exodus/schemasafe/1.0.0-rc.9: - resolution: {integrity: sha512-dGGHpb61hLwifAu7sotuHFDBw6GTdpG8aKC0fsK17EuTzMRvUrH7lEAr6LTJ+sx3AZYed9yZ77rltVDHyg2hRg==} - dev: true - - /@fal-works/esbuild-plugin-global-externals/2.1.2: - resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} - dev: true - - /@firebase/analytics-compat/0.2.0_5z7svkifsmkn6ro3hru7lnxwrq: - resolution: {integrity: sha512-brk8IN4ErWiZoB/UdJ0mWZhQOKt90ztv4MUwQjhuYJ4iwnVMz0Mzj9+tplU1hVpSZXdfbKQFfRN9kp/3sTiyWw==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/analytics': 0.9.0_@firebase+app@0.9.0 - '@firebase/analytics-types': 0.8.0 - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/analytics-types/0.8.0: - resolution: {integrity: sha512-iRP+QKI2+oz3UAh4nPEq14CsEjrjD6a5+fuypjScisAh9kXKFvdJOZJDwk7kikLvWVLGEs9+kIUS4LPQV7VZVw==} - dev: false - - /@firebase/analytics/0.9.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-cE6JAvaGDVhn3B09VuQ5pATLCtmQg3AUSDuCmMNzWlP7+12LBarV1JcGWKIi7YQK2ks3B73wRsawi08XKwsolQ==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/installations': 0.6.0_@firebase+app@0.9.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - dev: false - - /@firebase/app-check-compat/0.3.0_5z7svkifsmkn6ro3hru7lnxwrq: - resolution: {integrity: sha512-CJFHWGMvWRkkvLPTvWdLrEYnfH7WS9zFLsWctSzRjQnzg6dQUTs5FDyg9RN7BIWoaSr9q7FTxkRnsOgardDPLA==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-check': 0.6.0_@firebase+app@0.9.0 - '@firebase/app-check-types': 0.5.0 - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/app-check-interop-types/0.2.0: - resolution: {integrity: sha512-+3PQIeX6/eiVK+x/yg8r6xTNR97fN7MahFDm+jiQmDjcyvSefoGuTTNQuuMScGyx3vYUBeZn+Cp9kC0yY/9uxQ==} - dev: false - - /@firebase/app-check-types/0.5.0: - resolution: {integrity: sha512-uwSUj32Mlubybw7tedRzR24RP8M8JUVR3NPiMk3/Z4bCmgEKTlQBwMXrehDAZ2wF+TsBq0SN1c6ema71U/JPyQ==} - dev: false - - /@firebase/app-check/0.6.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-DevuiUQujsG18NQ1fQ1g2X+75Vp1YfSxPsw363/HE2+ABmCWHf4ByPmxEf16y4PVcqJ2MZqYv8kXZYxzRJCS4g==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - dev: false - - /@firebase/app-compat/0.2.0: - resolution: {integrity: sha512-Y8Cpuheai61jCdVflt437I94n8cdRbXY0e1dQMmTWHCShJUfWwpa5y2ZMnxClWnorXy9hC/3yNZMVlu79f1zGA==} - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - dev: false - - /@firebase/app-types/0.9.0: - resolution: {integrity: sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q==} - dev: false - - /@firebase/app/0.9.0: - resolution: {integrity: sha512-sa15stSK6FoGW4mCeAVDt0TvBFxPjvNcG2rhacGudOzMaW3g2TS326zXTFG+p5jnTCPZ2SO5TTSiGHn1NNcD9Q==} - dependencies: - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - idb: 7.0.1 - tslib: 2.4.1 - dev: false - - /@firebase/auth-compat/0.3.0_z6klzwxqggigirvqix3ggnu6f4: - resolution: {integrity: sha512-tcofcrQKBOo5Wrz59onWtZDJfVW09auvG/XRh7lZ4yfEWdGerTJXmEdQU6j3E8AnJ3X91BYltNYhh0ZJOoCJqQ==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/auth': 0.21.0_@firebase+app@0.9.0 - '@firebase/auth-types': 0.12.0_ymjb4f6a56kabcdqyfm4cet2ly - '@firebase/component': 0.6.0 - '@firebase/util': 1.8.0 - node-fetch: 2.6.7 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/auth-interop-types/0.2.0_ymjb4f6a56kabcdqyfm4cet2ly: - resolution: {integrity: sha512-7Mt2qzwvu5X3Qxz24gjj0qITrBsMmy1W4vGBP8TZRuQrjA4OTlGVCTG8ysvweZ3xpdl1XGhBsIjo2KjfOPg0xA==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.8.0 - dev: false - - /@firebase/auth-types/0.12.0_ymjb4f6a56kabcdqyfm4cet2ly: - resolution: {integrity: sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.8.0 - dev: false - - /@firebase/auth/0.21.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-kXOQl/hyLuGKxs0r2icLsDmAyeO0uM4zV9Q+fx6VE8Ncl94TBUc/n895GSrF3RkNHdiq/DZxV/PUCZ/ozPQNKw==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - node-fetch: 2.6.7 - tslib: 2.4.1 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/component/0.6.0: - resolution: {integrity: sha512-9hyNc4OmrXMtthDJq6zyJHll/UIYBWYmMG3rXty2eMeWxHWB0vlsq3AOI+k14PL15aSBAQolv0EZJWVJv/gCEg==} - dependencies: - '@firebase/util': 1.8.0 - tslib: 2.5.0 - dev: false - - /@firebase/database-compat/0.3.0_@firebase+app-types@0.9.0: - resolution: {integrity: sha512-5kzhXdACd+RX/G8k/DKYAuiMYHDHIZ9WFV/ccVoPsC+bxIQEgPilDEtkljY5ZxiKbUj+PEOSYUfYdV/LQMJatQ==} - dependencies: - '@firebase/component': 0.6.0 - '@firebase/database': 0.14.0_@firebase+app-types@0.9.0 - '@firebase/database-types': 0.10.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app-types' - dev: false - - /@firebase/database-types/0.10.0: - resolution: {integrity: sha512-jZHI1fY1tm+8heLR4sbgJHtSYI2kTlSp4QTXWALwdT+dfST5OlZYsZeb+hGWeqjHEElzUnkLbw8XuZSy9Uy6rA==} - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.8.0 - dev: false - - /@firebase/database/0.14.0_@firebase+app-types@0.9.0: - resolution: {integrity: sha512-SM5eri3eGuPjQdXBRObqKTsgmkRwrSGsbgtD43EpGzU+lIeBVLqwRzfcFialYrWzFFI5V7hWXdS2oJxAkfnBFw==} - dependencies: - '@firebase/auth-interop-types': 0.2.0_ymjb4f6a56kabcdqyfm4cet2ly - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - faye-websocket: 0.11.4 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app-types' - dev: false - - /@firebase/firestore-compat/0.3.0_z6klzwxqggigirvqix3ggnu6f4: - resolution: {integrity: sha512-ckU4mkziDnsFKxgYv+OAJHPuNpti2RjyoeIAqz3EqRHAsYFC70U5w4aXC2Sbu2jJp3Ba2BoD7MV/4Qb2A7CJtw==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/firestore': 3.8.0_@firebase+app@0.9.0 - '@firebase/firestore-types': 2.5.1_ymjb4f6a56kabcdqyfm4cet2ly - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/firestore-types/2.5.1_ymjb4f6a56kabcdqyfm4cet2ly: - resolution: {integrity: sha512-xG0CA6EMfYo8YeUxC8FeDzf6W3FX1cLlcAGBYV6Cku12sZRI81oWcu61RSKM66K6kUENP+78Qm8mvroBcm1whw==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.8.0 - dev: false - - /@firebase/firestore/3.8.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-aKwfZ73FmOV8e/dN0anDtrq6+1IhX4zmjxUcXcgaypZ14q6bq0QpUdlRxjsfiUQ5m3H3MwWWIFOcT5Xa89sIkw==} - engines: {node: '>=10.10.0'} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - '@firebase/webchannel-wrapper': 0.9.0 - '@grpc/grpc-js': 1.7.3 - '@grpc/proto-loader': 0.6.13 - node-fetch: 2.6.7 - tslib: 2.4.1 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/functions-compat/0.3.0_z6klzwxqggigirvqix3ggnu6f4: - resolution: {integrity: sha512-xOEdqOVeHXJ2ZjDbTntNGLl1lgW9umx73bWXJn9h68bSD4f9ldIVoz+h15s8i/e1pJOO/LlEp2BMvoA35U1P/Q==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/functions': 0.9.0_mw76ib4woycgbhoj6pqh7xkrde - '@firebase/functions-types': 0.6.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/functions-types/0.6.0: - resolution: {integrity: sha512-hfEw5VJtgWXIRf92ImLkgENqpL6IWpYaXVYiRkFY1jJ9+6tIhWM7IzzwbevwIIud/jaxKVdRzD7QBWfPmkwCYw==} - dev: false - - /@firebase/functions/0.9.0_mw76ib4woycgbhoj6pqh7xkrde: - resolution: {integrity: sha512-na/+7uc9ViQVBadEsCVjBnbZsfUCMyS/x6SID1Nz4Z5nkhuxrls9Jcv7jc28tMqHR0VpoGq8W6oLProyjT8JPg==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/app-check-interop-types': 0.2.0 - '@firebase/auth-interop-types': 0.2.0_ymjb4f6a56kabcdqyfm4cet2ly - '@firebase/component': 0.6.0 - '@firebase/messaging-interop-types': 0.2.0 - '@firebase/util': 1.8.0 - node-fetch: 2.6.7 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/installations-compat/0.2.0_z6klzwxqggigirvqix3ggnu6f4: - resolution: {integrity: sha512-EqCU8C9XPQN6npfTCW+6agzQ0yPLvbSCY5WROdnU1ZJfOsGFrMMVMRk42XBzah1dHBoSQYggVaixEzJUOH7zbQ==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/installations': 0.6.0_@firebase+app@0.9.0 - '@firebase/installations-types': 0.5.0_@firebase+app-types@0.9.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - dev: false - - /@firebase/installations-types/0.5.0_@firebase+app-types@0.9.0: - resolution: {integrity: sha512-9DP+RGfzoI2jH7gY4SlzqvZ+hr7gYzPODrbzVD82Y12kScZ6ZpRg/i3j6rleto8vTFC8n6Len4560FnV1w2IRg==} - peerDependencies: - '@firebase/app-types': 0.x - dependencies: - '@firebase/app-types': 0.9.0 - dev: false - - /@firebase/installations/0.6.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-Aks56ThZs1MsM0qJzJxhdeXak+Ob3tjd3JSY2poJptreLWsIOSBCxYO7Ev4yZ7DE7twMdZ0x70NhQ1ceXfdy0w==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/util': 1.8.0 - idb: 7.0.1 - tslib: 2.4.1 - dev: false - - /@firebase/logger/0.4.0: - resolution: {integrity: sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA==} - dependencies: - tslib: 2.5.0 - dev: false - - /@firebase/messaging-compat/0.2.0_5z7svkifsmkn6ro3hru7lnxwrq: - resolution: {integrity: sha512-Qk9W9lVmTO67bR5jCaQ9HqS9MipkCuPGKCcO5JnnDd/p+Y2beWzScYxwzYGh9pEga3qzDAMSCB1PYoNgNTMzew==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/messaging': 0.12.0_@firebase+app@0.9.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/messaging-interop-types/0.2.0: - resolution: {integrity: sha512-ujA8dcRuVeBixGR9CtegfpU4YmZf3Lt7QYkcj693FFannwNuZgfAYaTmbJ40dtjB81SAu6tbFPL9YLNT15KmOQ==} - dev: false - - /@firebase/messaging/0.12.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-M+LWaBH392SLF7/wAH5byJrP5f1MpromUG02NIr0sbgJ6Ot2nc+qDrDGjKF4qLXFqYzhNRlhskCCdf0ClgDM0A==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/installations': 0.6.0_@firebase+app@0.9.0 - '@firebase/messaging-interop-types': 0.2.0 - '@firebase/util': 1.8.0 - idb: 7.0.1 - tslib: 2.4.1 - dev: false - - /@firebase/performance-compat/0.2.0_5z7svkifsmkn6ro3hru7lnxwrq: - resolution: {integrity: sha512-iO0fspVpiVOGxR08Y51nXoSMPH/bdRkRVQXYo4wuDDfQoZ5WZ0DXQuE0kXy3/T9QgqXdr8tSU0P0nil/jvnOcg==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/performance': 0.6.0_@firebase+app@0.9.0 - '@firebase/performance-types': 0.2.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/performance-types/0.2.0: - resolution: {integrity: sha512-kYrbr8e/CYr1KLrLYZZt2noNnf+pRwDq2KK9Au9jHrBMnb0/C9X9yWSXmZkFt4UIdsQknBq8uBB7fsybZdOBTA==} - dev: false - - /@firebase/performance/0.6.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-mmCQ/8F0hQZ+J+JBvfQPlPAgKIRZccYW6N9321NbX8swd7EQP3dsW905RBmdXRsbjBpBqhn20zcQU6TDOKRwYA==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/installations': 0.6.0_@firebase+app@0.9.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - dev: false - - /@firebase/remote-config-compat/0.2.0_5z7svkifsmkn6ro3hru7lnxwrq: - resolution: {integrity: sha512-2t+w4ngp1DPtZc04a6IjicbUGBpLb/MuFPlqpT8kHNqa/fNvA+ZFcAlEtHvzjS4o9rnTfjHgB+OJMgFP+r9OOw==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/logger': 0.4.0 - '@firebase/remote-config': 0.4.0_@firebase+app@0.9.0 - '@firebase/remote-config-types': 0.3.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - dev: false - - /@firebase/remote-config-types/0.3.0: - resolution: {integrity: sha512-RtEH4vdcbXZuZWRZbIRmQVBNsE7VDQpet2qFvq6vwKLBIQRQR5Kh58M4ok3A3US8Sr3rubYnaGqZSurCwI8uMA==} - dev: false - - /@firebase/remote-config/0.4.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-sedVYE4PwN4qtXfb7EkUYe9mz7hqBP/3y3c7WRMmTuh2VRNz5C5+NYULr5zySeJq+UZd6KyaS+KUOIxmx70tTw==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/installations': 0.6.0_@firebase+app@0.9.0 - '@firebase/logger': 0.4.0 - '@firebase/util': 1.8.0 - tslib: 2.4.1 - dev: false - - /@firebase/storage-compat/0.2.0_z6klzwxqggigirvqix3ggnu6f4: - resolution: {integrity: sha512-w+7CyZyZ53YQWlTb8YOQ9YcmScgDwkvkXhpUbRWHlvlzAs06l0au42MydmHCeeTcSqvLOzpgURiVfm15ZifARg==} - peerDependencies: - '@firebase/app-compat': 0.x - dependencies: - '@firebase/app-compat': 0.2.0 - '@firebase/component': 0.6.0 - '@firebase/storage': 0.10.0_@firebase+app@0.9.0 - '@firebase/storage-types': 0.7.0_ymjb4f6a56kabcdqyfm4cet2ly - '@firebase/util': 1.8.0 - tslib: 2.4.1 - transitivePeerDependencies: - - '@firebase/app' - - '@firebase/app-types' - - encoding - dev: false - - /@firebase/storage-types/0.7.0_ymjb4f6a56kabcdqyfm4cet2ly: - resolution: {integrity: sha512-n/8pYd82hc9XItV3Pa2KGpnuJ/2h/n/oTAaBberhe6GeyWQPnsmwwRK94W3GxUwBA/ZsszBAYZd7w7tTE+6XXA==} - peerDependencies: - '@firebase/app-types': 0.x - '@firebase/util': 1.x - dependencies: - '@firebase/app-types': 0.9.0 - '@firebase/util': 1.8.0 - dev: false - - /@firebase/storage/0.10.0_@firebase+app@0.9.0: - resolution: {integrity: sha512-2rp7+/bQ1gkUgrqDv5qHf/vlPAOKV+a/h1tnZ8D9zN0/6wc42gqFTORJUZj/A4efVnX7Ix8MWHBe4woO/2Th0w==} - peerDependencies: - '@firebase/app': 0.x - dependencies: - '@firebase/app': 0.9.0 - '@firebase/component': 0.6.0 - '@firebase/util': 1.8.0 - node-fetch: 2.6.7 - tslib: 2.4.1 - transitivePeerDependencies: - - encoding - dev: false - - /@firebase/util/1.8.0: - resolution: {integrity: sha512-clK6pTTxIiLMYz4UrvDTVAs2rIaOiroAuFdX67C0JalvEwzi6Vv8li6xAGj38tkj7Qax06mosM1fQkxf2h4VTg==} - dependencies: - tslib: 2.4.1 - dev: false - - /@firebase/webchannel-wrapper/0.9.0: - resolution: {integrity: sha512-BpiZLBWdLFw+qFel9p3Zs1jD6QmH7Ii4aTDu6+vx8ShdidChZUXqDhYJly4ZjSgQh54miXbBgBrk0S+jTIh/Qg==} - dev: false - - /@floating-ui/core/1.1.0: - resolution: {integrity: sha512-zbsLwtnHo84w1Kc8rScAo5GMk1GdecSlrflIbfnEBJwvTSj1SL6kkOYV+nHraMCPEy+RNZZUaZyL8JosDGCtGQ==} - dev: false - - /@floating-ui/dom/1.1.0: - resolution: {integrity: sha512-TSogMPVxbRe77QCj1dt8NmRiJasPvuc+eT5jnJ6YpLqgOD2zXc5UA3S1qwybN+GVCDNdKfpKy1oj8RpzLJvh6A==} - dependencies: - '@floating-ui/core': 1.1.0 - dev: false - - /@floating-ui/react-dom/1.2.1_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-YCLlqibZtgUhxUpxkSp1oekvYgH/jI4KdZEJv85E62twlZHN43xdlQNe6JcF4ROD3/Zu6juNHN+aOygN+6yZjg==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - '@floating-ui/dom': 1.1.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /@formatjs/ecma402-abstract/1.14.3: - resolution: {integrity: sha512-SlsbRC/RX+/zg4AApWIFNDdkLtFbkq3LNoZWXZCE/nHVKqoIJyaoQyge/I0Y38vLxowUn9KTtXgusLD91+orbg==} - dependencies: - '@formatjs/intl-localematcher': 0.2.32 - tslib: 2.4.1 - dev: false - - /@formatjs/fast-memoize/1.2.7: - resolution: {integrity: sha512-hPeM5LXUUjtCKPybWOUAWpv8lpja8Xz+uKprFPJcg5F2Rd+/bf1E0UUsLRpaAgOReAf5HMRtoIgv/UcyPICrTQ==} - dependencies: - tslib: 2.5.0 - dev: false - - /@formatjs/icu-messageformat-parser/2.1.14: - resolution: {integrity: sha512-0KqeVOb72losEhUW+59vhZGGd14s1f35uThfEMVKZHKLEObvJdFTiI3ZQwvTMUCzLEMxnS6mtnYPmG4mTvwd3Q==} - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - '@formatjs/icu-skeleton-parser': 1.3.18 - tslib: 2.4.1 - dev: false - - /@formatjs/icu-skeleton-parser/1.3.18: - resolution: {integrity: sha512-ND1ZkZfmLPcHjAH1sVpkpQxA+QYfOX3py3SjKWMUVGDow18gZ0WPqz3F+pJLYQMpS2LnnQ5zYR2jPVYTbRwMpg==} - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - tslib: 2.5.0 - dev: false - - /@formatjs/intl-displaynames/6.2.3: - resolution: {integrity: sha512-teB0L68MDGM8jEKQg55w7nvFjzeLHE6e3eK/04s+iuEVYYmvjjiHJKHrthKENzcJ0F6mHf/AwXrbX+1mKxT6AQ==} - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - '@formatjs/intl-localematcher': 0.2.32 - tslib: 2.4.1 - dev: false - - /@formatjs/intl-listformat/7.1.7: - resolution: {integrity: sha512-Zzf5ruPpfJnrAA2hGgf/6pMgQ3tx9oJVhpqycFDavHl3eEzrwdHddGqGdSNwhd0bB4NAFttZNQdmKDldc5iDZw==} - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - '@formatjs/intl-localematcher': 0.2.32 - tslib: 2.4.1 - dev: false - - /@formatjs/intl-localematcher/0.2.32: - resolution: {integrity: sha512-k/MEBstff4sttohyEpXxCmC3MqbUn9VvHGlZ8fauLzkbwXmVrEeyzS+4uhrvAk9DWU9/7otYWxyDox4nT/KVLQ==} - dependencies: - tslib: 2.5.0 - dev: false - - /@formatjs/intl/2.6.3_typescript@4.9.5: - resolution: {integrity: sha512-JaVZk14U/GypVfCZPevQ0KdruFkq16FXx7g398/Dm+YEx/W7sRiftbZeDy4wQ7WGryb45e763XycxD9o/vm9BA==} - peerDependencies: - typescript: ^4.7 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - '@formatjs/fast-memoize': 1.2.7 - '@formatjs/icu-messageformat-parser': 2.1.14 - '@formatjs/intl-displaynames': 6.2.3 - '@formatjs/intl-listformat': 7.1.7 - intl-messageformat: 10.2.5 - tslib: 2.4.1 - typescript: 4.9.5 - dev: false - - /@fortawesome/fontawesome-common-types/6.2.1: - resolution: {integrity: sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ==} - engines: {node: '>=6'} - requiresBuild: true - dev: false - - /@fortawesome/fontawesome-svg-core/6.2.1: - resolution: {integrity: sha512-HELwwbCz6C1XEcjzyT1Jugmz2NNklMrSPjZOWMlc+ZsHIVk+XOvOXLGGQtFBwSyqfJDNgRq4xBCwWOaZ/d9DEA==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - '@fortawesome/fontawesome-common-types': 6.2.1 - dev: false - - /@fortawesome/free-brands-svg-icons/6.2.1: - resolution: {integrity: sha512-L8l4MfdHPmZlJ72PvzdfwOwbwcCAL0vx48tJRnI6u1PJXh+j2f3yDoKyQgO3qjEsgD5Fr2tQV/cPP8F/k6aUig==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - '@fortawesome/fontawesome-common-types': 6.2.1 - dev: false - - /@fortawesome/free-regular-svg-icons/6.2.1: - resolution: {integrity: sha512-wiqcNDNom75x+pe88FclpKz7aOSqS2lOivZeicMV5KRwOAeypxEYWAK/0v+7r+LrEY30+qzh8r2XDaEHvoLsMA==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - '@fortawesome/fontawesome-common-types': 6.2.1 - dev: false - - /@fortawesome/free-solid-svg-icons/6.2.1: - resolution: {integrity: sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - '@fortawesome/fontawesome-common-types': 6.2.1 - dev: false - - /@fortawesome/react-fontawesome/0.1.19_chs37cqfjyeefvqfxhgbgy2rma: - resolution: {integrity: sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==} - peerDependencies: - '@fortawesome/fontawesome-svg-core': ~1 || ~6 - react: '>=16.x' - dependencies: - '@fortawesome/fontawesome-svg-core': 6.2.1 - prop-types: 15.8.1 - react: 17.0.2 - dev: false - - /@grpc/grpc-js/1.7.3: - resolution: {integrity: sha512-H9l79u4kJ2PVSxUNA08HMYAnUBLj9v6KjYQ7SQ71hOZcEXhShE/y5iQCesP8+6/Ik/7i2O0a10bPquIcYfufog==} - engines: {node: ^8.13.0 || >=10.10.0} - dependencies: - '@grpc/proto-loader': 0.7.4 - '@types/node': 17.0.45 - dev: false - - /@grpc/proto-loader/0.6.13: - resolution: {integrity: sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==} - engines: {node: '>=6'} - hasBin: true - dependencies: - '@types/long': 4.0.2 - lodash.camelcase: 4.3.0 - long: 4.0.0 - protobufjs: 6.11.3 - yargs: 16.2.0 - dev: false - - /@grpc/proto-loader/0.7.4: - resolution: {integrity: sha512-MnWjkGwqQ3W8fx94/c1CwqLsNmHHv2t0CFn+9++6+cDphC1lolpg9M2OU0iebIjK//pBNX9e94ho+gjx6vz39w==} - engines: {node: '>=6'} - hasBin: true - dependencies: - '@types/long': 4.0.2 - lodash.camelcase: 4.3.0 - long: 4.0.0 - protobufjs: 7.1.2 - yargs: 16.2.0 - dev: false - - /@headlessui/react/1.7.7_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-BqDOd/tB9u2tA0T3Z0fn18ktw+KbVwMnkxxsGPIH2hzssrQhKB5n/6StZOyvLYP/FsYtvuXfi9I0YowKPv2c1w==} - engines: {node: '>=10'} - peerDependencies: - react: ^16 || ^17 || ^18 - react-dom: ^16 || ^17 || ^18 - dependencies: - client-only: 0.0.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /@humanwhocodes/config-array/0.11.8: - resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer/1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema/1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - dev: true - - /@ibm-cloud/openapi-ruleset/0.37.3: - resolution: {integrity: sha512-saQM/1YTfhW7ou/mtmC4BMUhW/UM54aD47KBZucjrZLvAelzt8Lykm5zeN59Cu4cs/LBDEcvJfyZzDpPhdcVjQ==} - engines: {node: '>=12.0.0'} - dependencies: - '@stoplight/spectral-formats': 1.4.0 - '@stoplight/spectral-functions': 1.7.2 - '@stoplight/spectral-rulesets': 1.14.1 - lodash: 4.17.21 - transitivePeerDependencies: - - encoding - dev: true - - /@istanbuljs/load-nyc-config/1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - - /@istanbuljs/schema/0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true - - /@jest/console/29.3.1: - resolution: {integrity: sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - chalk: 4.1.2 - jest-message-util: 29.3.1 - jest-util: 29.3.1 - slash: 3.0.0 - dev: true - - /@jest/core/29.3.1_ts-node@10.9.1: - resolution: {integrity: sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/console': 29.3.1 - '@jest/reporters': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.7.1 - exit: 0.1.2 - graceful-fs: 4.2.10 - jest-changed-files: 29.2.0 - jest-config: 29.3.1_2263m44mchjafa7bz7l52hbcpa - jest-haste-map: 29.3.1 - jest-message-util: 29.3.1 - jest-regex-util: 29.2.0 - jest-resolve: 29.3.1 - jest-resolve-dependencies: 29.3.1 - jest-runner: 29.3.1 - jest-runtime: 29.3.1 - jest-snapshot: 29.3.1 - jest-util: 29.3.1 - jest-validate: 29.3.1 - jest-watcher: 29.3.1 - micromatch: 4.0.5 - pretty-format: 29.3.1 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - supports-color - - ts-node - dev: true - - /@jest/environment/29.3.1: - resolution: {integrity: sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - jest-mock: 29.3.1 - dev: true - - /@jest/expect-utils/29.3.1: - resolution: {integrity: sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.2.0 - dev: true - - /@jest/expect/29.3.1: - resolution: {integrity: sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.3.1 - jest-snapshot: 29.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/fake-timers/29.3.1: - resolution: {integrity: sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - '@sinonjs/fake-timers': 9.1.2 - '@types/node': 17.0.45 - jest-message-util: 29.3.1 - jest-mock: 29.3.1 - jest-util: 29.3.1 - dev: true - - /@jest/globals/29.3.1: - resolution: {integrity: sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.3.1 - '@jest/expect': 29.3.1 - '@jest/types': 29.3.1 - jest-mock: 29.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/reporters/29.3.1: - resolution: {integrity: sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@jridgewell/trace-mapping': 0.3.17 - '@types/node': 17.0.45 - chalk: 4.1.2 - collect-v8-coverage: 1.0.1 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-instrument: 5.2.1 - istanbul-lib-report: 3.0.0 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.5 - jest-message-util: 29.3.1 - jest-util: 29.3.1 - jest-worker: 29.3.1 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/schemas/29.0.0: - resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.24.51 - dev: true - - /@jest/source-map/29.2.0: - resolution: {integrity: sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jridgewell/trace-mapping': 0.3.17 - callsites: 3.1.0 - graceful-fs: 4.2.10 - dev: true - - /@jest/test-result/29.3.1: - resolution: {integrity: sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.3.1 - '@jest/types': 29.3.1 - '@types/istanbul-lib-coverage': 2.0.4 - collect-v8-coverage: 1.0.1 - dev: true - - /@jest/test-sequencer/29.3.1: - resolution: {integrity: sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.3.1 - graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 - slash: 3.0.0 - dev: true - - /@jest/transform/29.3.1: - resolution: {integrity: sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.20.12 - '@jest/types': 29.3.1 - '@jridgewell/trace-mapping': 0.3.17 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 - jest-regex-util: 29.2.0 - jest-util: 29.3.1 - micromatch: 4.0.5 - pirates: 4.0.5 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/types/29.3.1: - resolution: {integrity: sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.0.0 - '@types/istanbul-lib-coverage': 2.0.4 - '@types/istanbul-reports': 3.0.1 - '@types/node': 17.0.45 - '@types/yargs': 17.0.19 - chalk: 4.1.2 - dev: true - - /@joshwooding/vite-plugin-react-docgen-typescript/0.2.1_egung5nfepmolqa7uavvqho3gq: - resolution: {integrity: sha512-ou4ZJSXMMWHqGS4g8uNRbC5TiTWxAgQZiVucoUrOCWuPrTbkpJbmVyIi9jU72SBry7gQtuMEDp4YR8EEXAg7VQ==} - peerDependencies: - typescript: '>= 4.3.x' - vite: ^3.0.0 || ^4.0.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - glob: 7.2.3 - glob-promise: 4.2.2_glob@7.2.3 - magic-string: 0.27.0 - react-docgen-typescript: 2.2.2_typescript@4.9.5 - typescript: 4.9.5 - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - dev: true - - /@jridgewell/gen-mapping/0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - - /@jridgewell/gen-mapping/0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 - - /@jridgewell/resolve-uri/3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - - /@jridgewell/set-array/1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - - /@jridgewell/sourcemap-codec/1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - - /@jridgewell/trace-mapping/0.3.17: - resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - - /@jridgewell/trace-mapping/0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jsdevtools/ono/7.1.3: - resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} - dev: true - - /@jsep-plugin/regex/1.0.3_jsep@1.3.8: - resolution: {integrity: sha512-XfZgry4DwEZvSFtS/6Y+R48D7qJYJK6R9/yJFyUFHCIUMEEHuJ4X95TDgJp5QkmzfLYvapMPzskV5HpIDrREug==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 - dependencies: - jsep: 1.3.8 - dev: true - - /@jsep-plugin/ternary/1.1.3_jsep@1.3.8: - resolution: {integrity: sha512-qtLGzCNzPVJ3kdH6/zoLWDPjauHIKiLSBAR71Wa0+PWvGA8wODUQvRgxtpUA5YqAYL3CQ8S4qXhd/9WuWTZirg==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 - dependencies: - jsep: 1.3.8 - dev: true - - /@mattiasbuelens/web-streams-polyfill/0.2.1: - resolution: {integrity: sha512-oKuFCQFa3W7Hj7zKn0+4ypI8JFm4ZKIoncwAC6wd5WwFW2sL7O1hpPoJdSWpynQ4DJ4lQ6MvFoVDmCLilonDFg==} - engines: {node: '>= 8'} - deprecated: moved to web-streams-polyfill@2.0.0 - dependencies: - '@types/whatwg-streams': 0.0.7 - dev: false - - /@mdx-js/react/2.2.1_react@17.0.2: - resolution: {integrity: sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==} - peerDependencies: - react: '>=16' - dependencies: - '@types/mdx': 2.0.3 - '@types/react': 17.0.52 - react: 17.0.2 - dev: true - - /@monaco-editor/loader/1.3.2_monaco-editor@0.34.1: - resolution: {integrity: sha512-BTDbpHl3e47r3AAtpfVFTlAi7WXv4UQ/xZmz8atKl4q7epQV5e7+JbigFDViWF71VBi4IIBdcWP57Hj+OWuc9g==} - peerDependencies: - monaco-editor: '>= 0.21.0 < 1' - dependencies: - monaco-editor: 0.34.1 - state-local: 1.0.7 - dev: false - - /@monaco-editor/react/4.4.6_5rrpgbvkp3saaogcekwkrw2jia: - resolution: {integrity: sha512-Gr3uz3LYf33wlFE3eRnta4RxP5FSNxiIV9ENn2D2/rN8KgGAD8ecvcITRtsbbyuOuNkwbuHYxfeaz2Vr+CtyFA==} - peerDependencies: - monaco-editor: '>= 0.25.0 < 1' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@monaco-editor/loader': 1.3.2_monaco-editor@0.34.1 - monaco-editor: 0.34.1 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /@motionone/animation/10.15.1: - resolution: {integrity: sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==} - dependencies: - '@motionone/easing': 10.15.1 - '@motionone/types': 10.15.1 - '@motionone/utils': 10.15.1 - tslib: 2.5.0 - dev: false - - /@motionone/dom/10.12.0: - resolution: {integrity: sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==} - dependencies: - '@motionone/animation': 10.15.1 - '@motionone/generators': 10.15.1 - '@motionone/types': 10.15.1 - '@motionone/utils': 10.15.1 - hey-listen: 1.0.8 - tslib: 2.4.1 - dev: false - - /@motionone/easing/10.15.1: - resolution: {integrity: sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==} - dependencies: - '@motionone/utils': 10.15.1 - tslib: 2.5.0 - dev: false - - /@motionone/generators/10.15.1: - resolution: {integrity: sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==} - dependencies: - '@motionone/types': 10.15.1 - '@motionone/utils': 10.15.1 - tslib: 2.5.0 - dev: false - - /@motionone/types/10.15.1: - resolution: {integrity: sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==} - dev: false - - /@motionone/utils/10.15.1: - resolution: {integrity: sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==} - dependencies: - '@motionone/types': 10.15.1 - hey-listen: 1.0.8 - tslib: 2.5.0 - dev: false - - /@nicolo-ribaudo/eslint-scope-5-internals/5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir/2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat/2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk/1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - dev: true - - /@orval/angular/6.11.1: - resolution: {integrity: sha512-L1sdQ7b7cq5jtL2OBacpyQ2MwGRUcWm1U5BEJg0R+K3eWN7LfFAQk99karMEbre1C5U/s2BXh/hxmWHK24i1+A==} - dependencies: - '@orval/core': 6.11.1 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - dev: true - - /@orval/axios/6.11.1: - resolution: {integrity: sha512-iemXAYoTuguCIgzK4yHRuUWNxIYk8umpI7FYNYCk+YZ1MJfWa+GAKeem9Fzb3EbmWWvlH4bNfFkXsygvorS1nw==} - dependencies: - '@orval/core': 6.11.1 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - dev: true - - /@orval/core/6.11.1: - resolution: {integrity: sha512-0d8K4gmeMovYYdagRQ5pj0KsgtB8JKDYP/RjzQfr40ootAjbP6egaAjhSzogv0vfSr5GDwNPPzD+S0cK6pQsAw==} - dependencies: - '@apidevtools/swagger-parser': 10.1.0 - acorn: 8.8.2 - ajv: 8.12.0 - chalk: 4.1.2 - compare-versions: 4.1.4 - debug: 4.3.4 - esbuild: 0.15.18 - esutils: 2.0.3 - fs-extra: 10.1.0 - globby: 11.1.0 - ibm-openapi-validator: 0.88.3 - lodash.get: 4.4.2 - lodash.isempty: 4.4.0 - lodash.omit: 4.5.0 - lodash.uniq: 4.5.0 - lodash.uniqby: 4.7.0 - lodash.uniqwith: 4.5.0 - micromatch: 4.0.5 - openapi3-ts: 3.1.2 - swagger2openapi: 7.0.8 - validator: 13.7.0 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - dev: true - - /@orval/msw/6.11.1: - resolution: {integrity: sha512-1WA9nLBhvBTu0MZ0V+UAlipNMkOmhy0vv2RfcAGrqiq8TCHkdVvVOZvrIuQkJxYkELEBAXTPfGnIzqCVwRkwiA==} - dependencies: - '@orval/core': 6.11.1 - cuid: 2.1.8 - lodash.get: 4.4.2 - lodash.omit: 4.5.0 - openapi3-ts: 3.1.2 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - dev: true - - /@orval/query/6.11.1: - resolution: {integrity: sha512-FV5mGQ9fpyqPJl82AkGvft2WQGr0GLyrVp7k7Nrlr0I2j+F0PByvlvtvTbS0CCXY9m9ot6tE3NDXkISZEczG4w==} - dependencies: - '@orval/core': 6.11.1 - lodash.omitby: 4.6.0 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - dev: true - - /@orval/swr/6.11.1: - resolution: {integrity: sha512-Oi/cgNzFWU0ukXoq5RselfJLcoy9l+MmLpmgnqTghXewRq67q1iIc5ee5/8Kf9m36dLCfb7uk8m1i3e6F5LhwA==} - dependencies: - '@orval/core': 6.11.1 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - dev: true - - /@popperjs/core/2.11.6: - resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} - - /@protobufjs/aspromise/1.1.2: - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - dev: false - - /@protobufjs/base64/1.1.2: - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - dev: false - - /@protobufjs/codegen/2.0.4: - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - dev: false - - /@protobufjs/eventemitter/1.1.0: - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - dev: false - - /@protobufjs/fetch/1.1.0: - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - dev: false - - /@protobufjs/float/1.0.2: - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - dev: false - - /@protobufjs/inquire/1.1.0: - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - dev: false - - /@protobufjs/path/1.1.2: - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - dev: false - - /@protobufjs/pool/1.1.0: - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - dev: false - - /@protobufjs/utf8/1.1.0: - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - dev: false - - /@rollup/plugin-commonjs/22.0.2_rollup@2.79.1: - resolution: {integrity: sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==} - engines: {node: '>= 12.0.0'} - peerDependencies: - rollup: ^2.68.0 - dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.79.1 - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 7.2.3 - is-reference: 1.2.1 - magic-string: 0.25.9 - resolve: 1.22.1 - rollup: 2.79.1 - dev: true - - /@rollup/pluginutils/3.1.0_rollup@2.79.1: - resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} - engines: {node: '>= 8.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0 - dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 - picomatch: 2.3.1 - rollup: 2.79.1 - dev: true - - /@rollup/pluginutils/4.2.1: - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@rollup/pluginutils/5.0.2: - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.0 - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: true - - /@rushstack/eslint-patch/1.2.0: - resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==} - dev: true - - /@sentry/browser/6.19.7: - resolution: {integrity: sha512-oDbklp4O3MtAM4mtuwyZLrgO1qDVYIujzNJQzXmi9YzymJCuzMLSRDvhY83NNDCRxf0pds4DShgYeZdbSyKraA==} - engines: {node: '>=6'} - dependencies: - '@sentry/core': 6.19.7 - '@sentry/types': 6.19.7 - '@sentry/utils': 6.19.7 - tslib: 1.14.1 - dev: false - - /@sentry/core/6.19.7: - resolution: {integrity: sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw==} - engines: {node: '>=6'} - dependencies: - '@sentry/hub': 6.19.7 - '@sentry/minimal': 6.19.7 - '@sentry/types': 6.19.7 - '@sentry/utils': 6.19.7 - tslib: 1.14.1 - dev: false - - /@sentry/hub/6.19.7: - resolution: {integrity: sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA==} - engines: {node: '>=6'} - dependencies: - '@sentry/types': 6.19.7 - '@sentry/utils': 6.19.7 - tslib: 1.14.1 - dev: false - - /@sentry/minimal/6.19.7: - resolution: {integrity: sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ==} - engines: {node: '>=6'} - dependencies: - '@sentry/hub': 6.19.7 - '@sentry/types': 6.19.7 - tslib: 1.14.1 - dev: false - - /@sentry/react/6.19.7_react@17.0.2: - resolution: {integrity: sha512-VzJeBg/v41jfxUYPkH2WYrKjWc4YiMLzDX0f4Zf6WkJ4v3IlDDSkX6DfmWekjTKBho6wiMkSNy2hJ1dHfGZ9jA==} - engines: {node: '>=6'} - peerDependencies: - react: 15.x || 16.x || 17.x || 18.x - dependencies: - '@sentry/browser': 6.19.7 - '@sentry/minimal': 6.19.7 - '@sentry/types': 6.19.7 - '@sentry/utils': 6.19.7 - hoist-non-react-statics: 3.3.2 - react: 17.0.2 - tslib: 1.14.1 - dev: false - - /@sentry/tracing/6.19.7: - resolution: {integrity: sha512-ol4TupNnv9Zd+bZei7B6Ygnr9N3Gp1PUrNI761QSlHtPC25xXC5ssSD3GMhBgyQrcvpuRcCFHVNNM97tN5cZiA==} - engines: {node: '>=6'} - dependencies: - '@sentry/hub': 6.19.7 - '@sentry/minimal': 6.19.7 - '@sentry/types': 6.19.7 - '@sentry/utils': 6.19.7 - tslib: 1.14.1 - dev: false - - /@sentry/types/6.19.7: - resolution: {integrity: sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg==} - engines: {node: '>=6'} - dev: false - - /@sentry/utils/6.19.7: - resolution: {integrity: sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA==} - engines: {node: '>=6'} - dependencies: - '@sentry/types': 6.19.7 - tslib: 1.14.1 - dev: false - - /@sinclair/typebox/0.24.51: - resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==} - dev: true - - /@sinonjs/commons/1.8.6: - resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} - dependencies: - type-detect: 4.0.8 - dev: true - - /@sinonjs/fake-timers/9.1.2: - resolution: {integrity: sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==} - dependencies: - '@sinonjs/commons': 1.8.6 - dev: true - - /@stoplight/better-ajv-errors/1.0.3_ajv@8.12.0: - resolution: {integrity: sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==} - engines: {node: ^12.20 || >= 14.13} - peerDependencies: - ajv: '>=8' - dependencies: - ajv: 8.12.0 - jsonpointer: 5.0.1 - leven: 3.1.0 - dev: true - - /@stoplight/json-ref-readers/1.2.2: - resolution: {integrity: sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ==} - engines: {node: '>=8.3.0'} - dependencies: - node-fetch: 2.6.9 - tslib: 1.14.1 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/json-ref-resolver/3.1.5: - resolution: {integrity: sha512-uaKLITor7UF+JBtI84zs3aOWM0L79zp7w9TrBTwPtx5SLbaQQ4HadDKgX5yhFOLMApLdhwhiftF4c0GFanOxGg==} - engines: {node: '>=8.3.0'} - dependencies: - '@stoplight/json': 3.20.1 - '@stoplight/path': 1.3.2 - '@stoplight/types': 13.8.0 - '@types/urijs': 1.19.19 - dependency-graph: 0.11.0 - fast-memoize: 2.5.2 - immer: 9.0.19 - lodash: 4.17.21 - tslib: 2.5.0 - urijs: 1.19.11 - dev: true - - /@stoplight/json/3.20.1: - resolution: {integrity: sha512-FXfud+uWgIj1xv6nUO9WnmgmnVikaxJcbtR4XQt4C42n5c2qua3U05Z/3B57hP5TJRSj+tpn9ID6/bFeyYYlEg==} - engines: {node: '>=8.3.0'} - dependencies: - '@stoplight/ordered-object-literal': 1.0.4 - '@stoplight/path': 1.3.2 - '@stoplight/types': 13.8.0 - jsonc-parser: 2.2.1 - lodash: 4.17.21 - safe-stable-stringify: 1.1.1 - dev: true - - /@stoplight/ordered-object-literal/1.0.4: - resolution: {integrity: sha512-OF8uib1jjDs5/cCU+iOVy+GJjU3X7vk/qJIkIJFqwmlJKrrtijFmqwbu8XToXrwTYLQTP+Hebws5gtZEmk9jag==} - engines: {node: '>=8'} - dev: true - - /@stoplight/path/1.3.2: - resolution: {integrity: sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==} - engines: {node: '>=8'} - dev: true - - /@stoplight/spectral-cli/6.6.0: - resolution: {integrity: sha512-z46fnrvraaWMio8Y9RYYkLO+XdmtxOWpy5qNJF3CsmWua0FZ4iOTryb5Cm3GkB0wEtqxNUCBUHvoo4hS6Noyqg==} - engines: {node: ^12.20 || >= 14.13} - hasBin: true - dependencies: - '@stoplight/json': 3.20.1 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.16.0 - '@stoplight/spectral-parsers': 1.0.2 - '@stoplight/spectral-ref-resolver': 1.0.2 - '@stoplight/spectral-ruleset-bundler': 1.5.0 - '@stoplight/spectral-ruleset-migrator': 1.9.1 - '@stoplight/spectral-rulesets': 1.14.1 - '@stoplight/spectral-runtime': 1.1.2 - '@stoplight/types': 13.8.0 - chalk: 4.1.2 - cliui: 7.0.4 - eol: 0.9.1 - fast-glob: 3.2.7 - lodash: 4.17.21 - pony-cause: 1.1.1 - proxy-agent: 5.0.0 - stacktracey: 2.1.8 - strip-ansi: 6.0.1 - text-table: 0.2.0 - tslib: 2.5.0 - yargs: 17.3.1 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@stoplight/spectral-core/1.16.0: - resolution: {integrity: sha512-W/NG+wV2UffwLExboqEa04/JbjGhiSTOl7GghLWYP4NKxZGaO6karP6fIxRBOnm34n1qyoZv9thsjSe92MWcDw==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - '@stoplight/better-ajv-errors': 1.0.3_ajv@8.12.0 - '@stoplight/json': 3.20.1 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-parsers': 1.0.2 - '@stoplight/spectral-ref-resolver': 1.0.3 - '@stoplight/spectral-runtime': 1.1.2 - '@stoplight/types': 13.6.0 - '@types/es-aggregate-error': 1.0.2 - '@types/json-schema': 7.0.11 - ajv: 8.12.0 - ajv-errors: 3.0.0_ajv@8.12.0 - ajv-formats: 2.1.1_ajv@8.12.0 - es-aggregate-error: 1.0.9 - jsonpath-plus: 7.1.0 - lodash: 4.17.21 - lodash.topath: 4.5.2 - minimatch: 3.1.2 - nimma: 0.2.2 - pony-cause: 1.1.1 - simple-eval: 1.0.0 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-formats/1.4.0: - resolution: {integrity: sha512-j9VQukDzgqDSi26rK9LqsbXrqtkeIsPSPgEf5/sxRsmeF2bwWUhSjYXgYin4flSZ7owFZjZWQ3o0Qq3iApi2JQ==} - engines: {node: '>=12'} - dependencies: - '@stoplight/json': 3.20.1 - '@stoplight/spectral-core': 1.16.0 - '@types/json-schema': 7.0.11 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-functions/1.7.2: - resolution: {integrity: sha512-f+61/FtIkQeIo+a269CeaeqjpyRsgDyIk6DGr7iS4hyuk1PPk7Uf6MNRDs9FEIBh7CpdEJ+HSHbMLwgpymWTIw==} - engines: {node: '>=12'} - dependencies: - '@stoplight/better-ajv-errors': 1.0.3_ajv@8.12.0 - '@stoplight/json': 3.20.1 - '@stoplight/spectral-core': 1.16.0 - '@stoplight/spectral-formats': 1.4.0 - '@stoplight/spectral-runtime': 1.1.2 - ajv: 8.12.0 - ajv-draft-04: 1.0.0_ajv@8.12.0 - ajv-errors: 3.0.0_ajv@8.12.0 - ajv-formats: 2.1.1_ajv@8.12.0 - lodash: 4.17.21 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-parsers/1.0.2: - resolution: {integrity: sha512-ZQXknJ+BM5Re4Opj4cgVlHgG2qyOk/wznKJq3Vf1qsBEg2CNzN0pJmSB0deRqW0kArqm44qpb8c+cz3F2rgMtw==} - engines: {node: '>=12'} - dependencies: - '@stoplight/json': 3.20.1 - '@stoplight/types': 13.8.0 - '@stoplight/yaml': 4.2.3 - tslib: 2.5.0 - dev: true - - /@stoplight/spectral-ref-resolver/1.0.2: - resolution: {integrity: sha512-ah6NIB/O1EdEaEu89So3LmtbKRXPVnSElgQ7oBRE9S4/VOedSqyXn+qqMd40tGnO2CsKgZaFUYXdSEHOshpHYw==} - engines: {node: '>=12'} - dependencies: - '@stoplight/json-ref-readers': 1.2.2 - '@stoplight/json-ref-resolver': 3.1.5 - '@stoplight/spectral-runtime': 1.1.2 - dependency-graph: 0.11.0 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-ref-resolver/1.0.3: - resolution: {integrity: sha512-pj+bH4SH8hcWlnV787WD7P0/En7LA3EfZMvG1JUGMW/7bFd9AaZZXNkh5j0ve8qnPlwP8F4SH/2Cnr1tXOXCVw==} - engines: {node: '>=12'} - dependencies: - '@stoplight/json-ref-readers': 1.2.2 - '@stoplight/json-ref-resolver': 3.1.5 - '@stoplight/spectral-runtime': 1.1.2 - dependency-graph: 0.11.0 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-ruleset-bundler/1.5.0: - resolution: {integrity: sha512-I1ZbhnJtRTi0lG6oXA1r8J6KLxoZKkNB3aSdrNJJTHoo/AccMSMhV4ey8zbLsYNsJ/9ywR5ttkBAbyGuo3Jtxg==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - '@rollup/plugin-commonjs': 22.0.2_rollup@2.79.1 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.16.0 - '@stoplight/spectral-formats': 1.4.0 - '@stoplight/spectral-functions': 1.7.2 - '@stoplight/spectral-parsers': 1.0.2 - '@stoplight/spectral-ref-resolver': 1.0.2 - '@stoplight/spectral-ruleset-migrator': 1.9.1 - '@stoplight/spectral-rulesets': 1.14.1 - '@stoplight/spectral-runtime': 1.1.2 - '@stoplight/types': 13.8.0 - '@types/node': 17.0.45 - pony-cause: 1.1.1 - rollup: 2.79.1 - tslib: 2.5.0 - validate-npm-package-name: 3.0.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-ruleset-migrator/1.9.1: - resolution: {integrity: sha512-TiH7UZIuHX+yb6EsWA9Z2ou455Wtki3z7SCkVRgd7WdzkD7O13R8ywqKoCUJ44UP7iuo1Ejnog18Rw4qJJE/fg==} - engines: {node: '>=12'} - dependencies: - '@stoplight/json': 3.20.1 - '@stoplight/ordered-object-literal': 1.0.4 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-functions': 1.7.2 - '@stoplight/spectral-runtime': 1.1.2 - '@stoplight/types': 13.8.0 - '@stoplight/yaml': 4.2.3 - '@types/node': 17.0.45 - ajv: 8.12.0 - ast-types: 0.14.2 - astring: 1.8.4 - reserved: 0.1.2 - tslib: 2.5.0 - validate-npm-package-name: 3.0.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-rulesets/1.14.1: - resolution: {integrity: sha512-tn6a5fYPFDwEY+/YyK/hcq2gcR5nSIBt7l+JGELb/2RdTzD5ikj2mfl2ua3uxbqOZytftFoOX5ewGZ0qQNrudw==} - engines: {node: '>=12'} - dependencies: - '@asyncapi/specs': 3.2.1 - '@stoplight/better-ajv-errors': 1.0.3_ajv@8.12.0 - '@stoplight/json': 3.20.1 - '@stoplight/spectral-core': 1.16.0 - '@stoplight/spectral-formats': 1.4.0 - '@stoplight/spectral-functions': 1.7.2 - '@stoplight/spectral-runtime': 1.1.2 - '@stoplight/types': 13.8.0 - '@types/json-schema': 7.0.11 - ajv: 8.12.0 - ajv-formats: 2.1.1_ajv@8.12.0 - json-schema-traverse: 1.0.0 - lodash: 4.17.21 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/spectral-runtime/1.1.2: - resolution: {integrity: sha512-fr5zRceXI+hrl82yAVoME+4GvJie8v3wmOe9tU+ZLRRNonizthy8qDi0Z/z4olE+vGreSDcuDOZ7JjRxFW5kTw==} - engines: {node: '>=12'} - dependencies: - '@stoplight/json': 3.20.1 - '@stoplight/path': 1.3.2 - '@stoplight/types': 12.5.0 - abort-controller: 3.0.0 - lodash: 4.17.21 - node-fetch: 2.6.9 - tslib: 2.5.0 - transitivePeerDependencies: - - encoding - dev: true - - /@stoplight/types/12.5.0: - resolution: {integrity: sha512-dwqYcDrGmEyUv5TWrDam5TGOxU72ufyQ7hnOIIDdmW5ezOwZaBFoR5XQ9AsH49w7wgvOqB2Bmo799pJPWnpCbg==} - engines: {node: '>=8'} - dependencies: - '@types/json-schema': 7.0.11 - utility-types: 3.10.0 - dev: true - - /@stoplight/types/13.6.0: - resolution: {integrity: sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==} - engines: {node: ^12.20 || >=14.13} - dependencies: - '@types/json-schema': 7.0.11 - utility-types: 3.10.0 - dev: true - - /@stoplight/types/13.8.0: - resolution: {integrity: sha512-5glKswz7y9aACh+a+JegID+4xX//4TsIdv7iPl29hWnOoWrnlPbg3Gjc4nYUXXgMSaSlSsA15JU/0+rE89fR4A==} - engines: {node: ^12.20 || >=14.13} - dependencies: - '@types/json-schema': 7.0.11 - utility-types: 3.10.0 - dev: true - - /@stoplight/yaml-ast-parser/0.0.48: - resolution: {integrity: sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==} - dev: true - - /@stoplight/yaml/4.2.3: - resolution: {integrity: sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==} - engines: {node: '>=10.8'} - dependencies: - '@stoplight/ordered-object-literal': 1.0.4 - '@stoplight/types': 13.8.0 - '@stoplight/yaml-ast-parser': 0.0.48 - tslib: 2.5.0 - dev: true - - /@storybook/addon-actions/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-3vyYC8o3bhC8wHIhCHzm0wznrkreEmg6joHyc4g/N6L27xpI4IiFufU7T38fYM3QOQfnAR++Cf7HBtB9A9uAaw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - dequal: 2.0.3 - lodash: 4.17.21 - polished: 4.2.2 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-inspector: 6.0.1_react@17.0.2 - telejson: 7.0.4 - ts-dedent: 2.2.0 - uuid-browser: 3.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-backgrounds/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-rDuQiUmFBBA/l/rpCB0Ei2NLwd111SkxgAhyhcjKpyPr2HeYwNAQRRqxphKf87Xn4LtE1kTaw9XYObvnZwfZyw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - memoizerific: 1.11.3 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-controls/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-BFJVYmp9jXfvHerHnipBcQJDIFOyhOUFPmfd5ub9zVZEWkhO21/HVqwXoBdhPARkZW3cYPq1U7kwU0CfJzK8YQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/blocks': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - lodash: 4.17.21 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-docs/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-2zHthuKB22aLdD7pMWgTKjDyrp8IlsQaY2a3fXwFWKPUVgxlfe9fTCcQ6fFnZz7p5Zyoy+aIR1GSsM/quWp6pA==} - peerDependencies: - '@storybook/mdx1-csf': '>=1.0.0-0' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@storybook/mdx1-csf': - optional: true - dependencies: - '@babel/core': 7.20.12 - '@babel/plugin-transform-react-jsx': 7.20.7_@babel+core@7.20.12 - '@jest/transform': 29.3.1 - '@mdx-js/react': 2.2.1_react@17.0.2 - '@storybook/blocks': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/csf-plugin': 7.0.0-beta.38 - '@storybook/csf-tools': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/mdx2-csf': 1.0.0-next.5 - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/postinstall': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - fs-extra: 11.1.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - remark-external-links: 8.0.0 - remark-slug: 6.1.0 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-essentials/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-qgt1J4lKO9jJKmihUcYC4lDywPEsDmkpC9fLKIXY6Ub/M1EFhvswBtBHIfi22HpSvdfi5ewpI4J0MmKwTsZ3/w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@storybook/addon-actions': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-backgrounds': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-controls': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-docs': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-highlight': 7.0.0-beta.38 - '@storybook/addon-measure': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-outline': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-toolbars': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/addon-viewport': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - '@storybook/mdx1-csf' - - supports-color - dev: true - - /@storybook/addon-highlight/7.0.0-beta.38: - resolution: {integrity: sha512-mjwOAwFBnw7n/Juu3mDgsbIzTJ38iz2FApVTGMw6I9qSB0T8wUPYqDGpM+gIhC5apYc4VPdOMXvnJfyZBAyR+Q==} - dependencies: - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.0.0-beta.38 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-links/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-s8zjrx34OI+yH0XthJssxYyGi9kFust8kGlsYLLgRcMYf91kL9NQsp7M4Y5TRCo5n8TIyBCdDkSEPNB46n2c3A==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/csf': 0.0.2-next.8 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/router': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-measure/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-BS1I+nHC1DtuMqQCdfQNIf0zKua8SrSk7w2ib7V/hoAKWv1yIpIY3xDm/29YqGgw0dpGl/reOwjYbkNDZrCO5w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-outline/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-GxZFieMl+svpBIzBYcQKU/MYos9QR7UjKq1bGPFMoc+hK7iNA5H2MTwICLhN3bOhzsxrPoikwfKjSPTjOql12Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-toolbars/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-FPW+CiRpccdzQphMzVTI31O8QxiRwlTAiUCrBrJj+fC9drL02IEDrtLJe4kMztLK8PSOTlkPlJ5YXz//lsronQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/addon-viewport/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-zDMX2w5kNHN1XwXiCUrmBjAqfkkvKoxZnGmdWOgjS+uXbwyqdBz4jFtlTydMhGnvx3z7R0Icnz2POEszWJNJqg==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - memoizerific: 1.11.3 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/blocks/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-wokrqvYw6dICer4BVWLdmP3KHJ0g+uEbJQvCzobVtLBvO0nsjWx+JWAgs7ih+6wNUF8Xw0iui/iL/LSEX/iYcw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@storybook/channels': 7.0.0-beta.38 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/components': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/csf': 0.0.2-next.8 - '@storybook/docs-tools': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/manager-api': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - '@types/lodash': 4.14.191 - color-convert: 2.0.1 - dequal: 2.0.3 - lodash: 4.17.21 - markdown-to-jsx: 7.1.8_react@17.0.2 - memoizerific: 1.11.3 - polished: 4.2.2 - react: 17.0.2 - react-colorful: 5.6.1_sfoxds7t5ydpegc3knd667wn6m - react-dom: 17.0.2_react@17.0.2 - ts-dedent: 2.2.0 - util-deprecate: 1.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/builder-manager/7.0.0-beta.38: - resolution: {integrity: sha512-bhQr/9wECvIXekJXvQSsadMkjwuOp3H5dMy8gfmrwaOj90HRdviuP39m746DFI82TJHagyFZswGJ6Cv2qAaQrQ==} - dependencies: - '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/manager': 7.0.0-beta.38 - '@storybook/node-logger': 7.0.0-beta.38 - '@types/ejs': 3.1.1 - '@types/find-cache-dir': 3.2.1 - '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15_esbuild@0.16.17 - browser-assert: 1.2.1 - ejs: 3.1.8 - esbuild: 0.16.17 - esbuild-plugin-alias: 0.2.1 - express: 4.18.2 - find-cache-dir: 3.3.2 - fs-extra: 11.1.0 - process: 0.11.10 - slash: 3.0.0 - util: 0.12.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/builder-vite/7.0.0-beta.38_egung5nfepmolqa7uavvqho3gq: - resolution: {integrity: sha512-FfgS3tHLbcF5O+g6IBjqwCR6UBrT+YnF4Ozgp/kCmXNEg/JVJ5W0yzYQXlFhp9Sbbpf8NghZiEPnNUinqbRm1w==} - peerDependencies: - '@preact/preset-vite': '*' - typescript: '>= 4.3.x' - vite: ^3.0.0 || ^4.0.0 - vite-plugin-glimmerx: '*' - peerDependenciesMeta: - '@preact/preset-vite': - optional: true - typescript: - optional: true - vite-plugin-glimmerx: - optional: true - dependencies: - '@storybook/channel-postmessage': 7.0.0-beta.38 - '@storybook/channel-websocket': 7.0.0-beta.38 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/csf-plugin': 7.0.0-beta.38 - '@storybook/mdx2-csf': 1.0.0-next.5 - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/preview': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - browser-assert: 1.2.1 - es-module-lexer: 0.9.3 - express: 4.18.2 - fs-extra: 11.1.0 - glob: 7.2.3 - glob-promise: 4.2.2_glob@7.2.3 - magic-string: 0.27.0 - rollup: 3.10.1 - slash: 3.0.0 - typescript: 4.9.5 - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/channel-postmessage/7.0.0-beta.38: - resolution: {integrity: sha512-brOLkukbfOxznnW/B8qfzYZGeyTtf9OtSQWrfSTdZv6eqy1fgY4LXSnfUmaKtHPS7K5eWwLGpPbdJI7PPxOklQ==} - dependencies: - '@storybook/channels': 7.0.0-beta.38 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - qs: 6.11.0 - telejson: 7.0.4 - dev: true - - /@storybook/channel-websocket/7.0.0-beta.38: - resolution: {integrity: sha512-XGQ/LjXA55qsdLck9o4HGjKEdM9tEKmiyRJds30Uj/zxfJETz6ODi/g/EEJkPtZ5QeQDqPzieC0AdNinasaB6w==} - dependencies: - '@storybook/channels': 7.0.0-beta.38 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - telejson: 7.0.4 - dev: true - - /@storybook/channels/7.0.0-beta.38: - resolution: {integrity: sha512-3Wr0jXpwIKppOHaputPLpZBwYYN7gQzqM0MYTQmw1e+lzblhdZkFAI0KaHrMWIEi70NLbsR48ZEVwyZVwrLMRw==} - dev: true - - /@storybook/cli/7.0.0-beta.38: - resolution: {integrity: sha512-0zFbXX59Fh6BvL6kWfDkdxG7F8KBwkqV6pObxq4qmwMhDpjV0HYwQotQ0aYK5Z6OuSq+WMqDY1iXszTWB6meqg==} - hasBin: true - dependencies: - '@babel/core': 7.20.12 - '@babel/preset-env': 7.20.2_@babel+core@7.20.12 - '@storybook/codemod': 7.0.0-beta.38 - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/core-server': 7.0.0-beta.38 - '@storybook/csf-tools': 7.0.0-beta.38 - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/telemetry': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - '@types/semver': 7.3.13 - boxen: 5.1.2 - chalk: 4.1.2 - commander: 6.2.1 - cross-spawn: 7.0.3 - detect-indent: 6.1.0 - envinfo: 7.8.1 - execa: 5.1.1 - express: 4.18.2 - find-up: 5.0.0 - fs-extra: 11.1.0 - get-port: 5.1.1 - giget: 1.0.0 - globby: 11.1.0 - jscodeshift: 0.13.1_@babel+preset-env@7.20.2 - leven: 3.1.0 - prompts: 2.4.2 - puppeteer-core: 2.1.1 - read-pkg-up: 7.0.1 - semver: 7.3.8 - shelljs: 0.8.5 - simple-update-notifier: 1.1.0 - strip-json-comments: 3.1.1 - tempy: 1.0.1 - ts-dedent: 2.2.0 - util-deprecate: 1.0.2 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true - - /@storybook/client-logger/7.0.0-beta.38: - resolution: {integrity: sha512-B2Q+rmZj+QbPFWpHwqI4Llf842jiZe2JuTNd8zaeuTYf4WS/gWKicOL6VtDxUF3mfCftrQT9gNEdjBwwca1HsQ==} - dependencies: - '@storybook/global': 5.0.0 - dev: true - - /@storybook/codemod/7.0.0-beta.38: - resolution: {integrity: sha512-k+f1a6fTCRq8xSxABlagQiAbjbY/2Yfbsh94gEA0mXjQpARSfDJS2kDro4guwadnlBL8PZy/RtqNX/3RvCx4JQ==} - dependencies: - '@babel/core': 7.20.12 - '@babel/preset-env': 7.20.2_@babel+core@7.20.12 - '@babel/types': 7.20.7 - '@storybook/csf': 0.0.2-next.8 - '@storybook/csf-tools': 7.0.0-beta.38 - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - cross-spawn: 7.0.3 - globby: 11.1.0 - jscodeshift: 0.13.1_@babel+preset-env@7.20.2 - lodash: 4.17.21 - prettier: 2.8.3 - recast: 0.23.1 - util: 0.12.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/components/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-AjxMwkXCcEwn7cq7yI5U2sTFctZzUKyUytUuxOS10+8uo8iA21bExLVht/z39bTQzHfh9ph433ArOR0bd9gWXw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/csf': 0.0.2-next.8 - '@storybook/global': 5.0.0 - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - memoizerific: 1.11.3 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - util-deprecate: 1.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/core-client/7.0.0-beta.38: - resolution: {integrity: sha512-RrBs8JT6r53dPkkbNR+dQqMdYQbZVxsS+1mhaBkIhj+vHpkcq2hW5iM68ilut7DcmpSuKt+Wr+skmH3ObNhD9g==} - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/core-common/7.0.0-beta.38: - resolution: {integrity: sha512-ldfhLxS4zHdb5jZp6HoW6efZ0Df+04V0AoioPCZ9DwgHmg1Ra/xB/r8rpOWkzIcW2dFdj1fMxcsRPRFaglASSA==} - dependencies: - '@babel/core': 7.20.12 - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - '@types/babel__core': 7.1.20 - '@types/express': 4.17.16 - '@types/node': 16.18.11 - '@types/pretty-hrtime': 1.0.1 - chalk: 4.1.2 - esbuild: 0.16.17 - esbuild-register: 3.4.2_esbuild@0.16.17 - express: 4.18.2 - file-system-cache: 2.0.2 - find-up: 5.0.0 - fs-extra: 11.1.0 - glob: 7.2.3 - handlebars: 4.7.7 - lazy-universal-dotenv: 4.0.0 - picomatch: 2.3.1 - pkg-dir: 5.0.0 - pretty-hrtime: 1.0.3 - resolve-from: 5.0.0 - slash: 3.0.0 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/core-events/7.0.0-beta.38: - resolution: {integrity: sha512-VzC+ssutXDheDeoDnnImVdyzzKxO4THANlM2hV8aekcRMzQe5MFSOy4kNu4bu7aA4okkz10f3Pj/TwEbgwkH0A==} - dev: true - - /@storybook/core-server/7.0.0-beta.38: - resolution: {integrity: sha512-16fVtaxaa370Lx+I1k429szUl1NcXXfQ/YonkaQBHMSOmAy4ZLjqzBDQZhpzaXYUIh3e9nuK9BQKZtd6IOC2ZQ==} - dependencies: - '@aw-web-design/x-default-browser': 1.4.88 - '@discoveryjs/json-ext': 0.5.7 - '@storybook/builder-manager': 7.0.0-beta.38 - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/csf': 0.0.2-next.8 - '@storybook/csf-tools': 7.0.0-beta.38 - '@storybook/docs-mdx': 0.0.1-next.6 - '@storybook/global': 5.0.0 - '@storybook/node-logger': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/telemetry': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - '@types/detect-port': 1.3.2 - '@types/node': 16.18.11 - '@types/node-fetch': 2.6.2 - '@types/pretty-hrtime': 1.0.1 - '@types/semver': 7.3.13 - better-opn: 2.1.1 - boxen: 5.1.2 - chalk: 4.1.2 - cli-table3: 0.6.3 - compression: 1.7.4 - detect-port: 1.5.1 - express: 4.18.2 - fs-extra: 11.1.0 - globby: 11.1.0 - ip: 2.0.0 - lodash: 4.17.21 - node-fetch: 2.6.8 - open: 8.4.0 - pretty-hrtime: 1.0.3 - prompts: 2.4.2 - read-pkg-up: 7.0.1 - semver: 7.3.8 - serve-favicon: 2.5.0 - slash: 3.0.0 - telejson: 7.0.4 - ts-dedent: 2.2.0 - util-deprecate: 1.0.2 - watchpack: 2.4.0 - ws: 8.12.0 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true - - /@storybook/csf-plugin/7.0.0-beta.38: - resolution: {integrity: sha512-xXRSKNnDHb5W6OTh8Laleo+XbVu+tjlnFYWJVfgi80aU2uZMsUremYiREyXWh/9rmDTslkteuXDDXn8Rpe8daQ==} - dependencies: - '@storybook/csf-tools': 7.0.0-beta.38 - unplugin: 0.10.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/csf-tools/7.0.0-beta.38: - resolution: {integrity: sha512-qx1RIcfx8ofshqadJTGd2SgM12F08NJhNJeNLW4WTU5+rv2rmZ/OfagUJDNBoeS9OOfveoxJSWAcCbE4ks1fOA==} - dependencies: - '@babel/types': 7.20.7 - '@storybook/csf': 0.0.2-next.8 - '@storybook/types': 7.0.0-beta.38 - fs-extra: 11.1.0 - recast: 0.23.1 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/csf/0.0.2-next.8: - resolution: {integrity: sha512-3T6rflW7D9q1iXOR+bidwoNbd9rVUTyjYH/sqsnYjbXhb/aOXsQzGKwNeq9QqZIFVpKfg5BoOF5i7DCMtoGknQ==} - dependencies: - expect-type: 0.14.2 - lodash: 4.17.21 - type-fest: 2.19.0 - dev: true - - /@storybook/docs-mdx/0.0.1-next.6: - resolution: {integrity: sha512-DjoSIXADmLJtdroXAjUotFiZlcZ2usWhqrS7aeOtZs0DVR0Ws5WQjnwtpDUXt8gryTSd+OZJ0cNsDcqg4JDEvQ==} - dev: true - - /@storybook/docs-tools/7.0.0-beta.38: - resolution: {integrity: sha512-7hLwcvZxnvBcdNemmo5eknqNQHxL+EbulQA14vLeqerSchQuaMS9Y/MNboHxPZkaFeKs+vWj4ansfl62yvcIKQ==} - dependencies: - '@babel/core': 7.20.12 - '@storybook/core-common': 7.0.0-beta.38 - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - '@types/doctrine': 0.0.3 - doctrine: 3.0.0 - lodash: 4.17.21 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/global/5.0.0: - resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} - dev: true - - /@storybook/manager-api/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-B2t6rOSUlPpFA86MOJCzVel11S1qay2lN+HLhw42a1P1ToeMri4uEYdzwnV7F8tcrxAys1tcDRLoQiPpx87DYg==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@storybook/channels': 7.0.0-beta.38 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/csf': 0.0.2-next.8 - '@storybook/global': 5.0.0 - '@storybook/router': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/theming': 7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m - '@storybook/types': 7.0.0-beta.38 - dequal: 2.0.3 - lodash: 4.17.21 - memoizerific: 1.11.3 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - semver: 7.3.8 - store2: 2.14.2 - telejson: 7.0.4 - ts-dedent: 2.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/manager/7.0.0-beta.38: - resolution: {integrity: sha512-qqj/rqrpd4KLDkqYuSVtoC1cPE3v/vDuri48DQwU+mxO07Xf3RN+QXfc1hUlS9r6eDXG8t9pOGZ3ZAz3lqevjw==} - dev: true - - /@storybook/mdx2-csf/1.0.0-next.5: - resolution: {integrity: sha512-02w0sgGZaK1agT050yCVhJ+o4rLHANWvLKWjQjeAsYbjneLC5ITt+3GDB4jRiWwJboZ8dHW1fGSK1Vg5fA34aQ==} - dev: true - - /@storybook/node-logger/7.0.0-beta.38: - resolution: {integrity: sha512-EJzYAFOZnKkM4WEl+vB+SC7GrpojdGh0Gv3MHuhRBh7fnXIL30ocVZkIlK+qt0fLy2yC/9FAFIFPX6akvhT9hQ==} - dependencies: - '@types/npmlog': 4.1.4 - chalk: 4.1.2 - npmlog: 5.0.1 - pretty-hrtime: 1.0.3 - dev: true - - /@storybook/postinstall/7.0.0-beta.38: - resolution: {integrity: sha512-KeWYbiIAW5S6FCNMCLgO8u4qLRsV1hLRQEle/z+I8AaggY4RheqiWa8hCupdXwKfkGdy7iJuSCHRUdNxaLnZ7A==} - dev: true - - /@storybook/preview-api/7.0.0-beta.38: - resolution: {integrity: sha512-ljt+1Uw2qYcQ1p2wTvNEj6OkEYctP9KBXSTo2fmOgFh+ti/jXvG0tjz33JOR2bh7hFrjp2xXUIBSWkKDTqheig==} - dependencies: - '@storybook/channel-postmessage': 7.0.0-beta.38 - '@storybook/channels': 7.0.0-beta.38 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-events': 7.0.0-beta.38 - '@storybook/csf': 0.0.2-next.8 - '@storybook/global': 5.0.0 - '@storybook/types': 7.0.0-beta.38 - '@types/qs': 6.9.7 - dequal: 2.0.3 - lodash: 4.17.21 - memoizerific: 1.11.3 - qs: 6.11.0 - slash: 3.0.0 - synchronous-promise: 2.0.16 - ts-dedent: 2.2.0 - util-deprecate: 1.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/preview/7.0.0-beta.38: - resolution: {integrity: sha512-eQ1lQ6WHU8h4ZKDTgCJj45qLawtejggDh84QZJ1rN/tFCOGnzS++aG/dhBBDWOa9FwWS18Mgmde1RrMsqH1/6A==} - dev: true - - /@storybook/react-vite/7.0.0-beta.38_ixkwjuwc6whfuuxbuybnyjw2h4: - resolution: {integrity: sha512-+5ZYku6qVGLq/6M/3xFR0wSSb5omzyuEB395+TxtVCF+Ha8h+rYnpDWaPHoF+rMD7TWdVxXNYwN8UiHJFSFjDQ==} - engines: {node: '>=16'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - vite: ^3.0.0 || ^4.0.0 - dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1_egung5nfepmolqa7uavvqho3gq - '@rollup/pluginutils': 4.2.1 - '@storybook/builder-vite': 7.0.0-beta.38_egung5nfepmolqa7uavvqho3gq - '@storybook/react': 7.0.0-beta.38_jgxnvbe4faw3ohf4h6p42qq6oy - '@vitejs/plugin-react': 3.0.1_vite@4.0.4 - ast-types: 0.14.2 - magic-string: 0.27.0 - react: 17.0.2 - react-docgen: 6.0.0-alpha.3 - react-dom: 17.0.2_react@17.0.2 - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - transitivePeerDependencies: - - '@preact/preset-vite' - - supports-color - - typescript - - vite-plugin-glimmerx - dev: true - - /@storybook/react/7.0.0-beta.38_jgxnvbe4faw3ohf4h6p42qq6oy: - resolution: {integrity: sha512-0h7yZjCuBhSMMOB51PGN/RA2gXZgLHIr64gr0JqNfM6TKLPTCsnhA88odwwmtEwExLqvnaB97matNpkeV4mbuw==} - engines: {node: '>=16.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-client': 7.0.0-beta.38 - '@storybook/docs-tools': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - '@storybook/preview-api': 7.0.0-beta.38 - '@storybook/types': 7.0.0-beta.38 - '@types/escodegen': 0.0.6 - '@types/estree': 0.0.51 - '@types/node': 16.18.11 - acorn: 7.4.1 - acorn-jsx: 5.3.2_acorn@7.4.1 - acorn-walk: 7.2.0 - escodegen: 2.0.0 - html-tags: 3.2.0 - lodash: 4.17.21 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-element-to-jsx-string: 15.0.0_sfoxds7t5ydpegc3knd667wn6m - ts-dedent: 2.2.0 - type-fest: 2.19.0 - typescript: 4.9.5 - util-deprecate: 1.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@storybook/router/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-Cx1/f6mAP8E5fRBsiA3lJksf+6IqYTCDmQ3sA/kbDobXslqy25lZ2OHuwXr9NzLwFQKwiZ3z0MMqMxYR0A7JEw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - memoizerific: 1.11.3 - qs: 6.11.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: true - - /@storybook/telemetry/7.0.0-beta.38: - resolution: {integrity: sha512-hdS7SPOXQC0Yl7ukvuIE4ebFUwrYCTUpHw7FQ3Xl8l3hDap5DAx/Bs/0I7zJb2qlzqwnDuWnS8ZReuUcCEgZMw==} - dependencies: - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/core-common': 7.0.0-beta.38 - chalk: 4.1.2 - detect-package-manager: 2.0.1 - fetch-retry: 5.0.3 - fs-extra: 11.1.0 - isomorphic-unfetch: 3.1.0 - nanoid: 3.3.4 - read-pkg-up: 7.0.1 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@storybook/theming/7.0.0-beta.38_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-ss9N8c8mATZxaWSOAKrouQHUbwQpZvE2wTEIf5T3MR/JN/Kz/DPU8uTH4DUcP6wntkDARoj5kH0200l0w3IbKA==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@emotion/use-insertion-effect-with-fallbacks': 1.0.0_react@17.0.2 - '@storybook/client-logger': 7.0.0-beta.38 - '@storybook/global': 5.0.0 - memoizerific: 1.11.3 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: true - - /@storybook/types/7.0.0-beta.38: - resolution: {integrity: sha512-S4CR/hlp9M5/BzlbUuih/MfqU8wSFwjA0R+Tukiwc+p8qPBx5W4/acGMEwEwBGMM3KXMbqvRZExyWjWyOkQZJQ==} - dependencies: - '@babel/core': 7.20.12 - '@storybook/channels': 7.0.0-beta.38 - '@types/babel__core': 7.1.20 - '@types/express': 4.17.16 - express: 4.18.2 - file-system-cache: 2.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@svgr/babel-plugin-add-jsx-attribute/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==} - engines: {node: '>=10'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /@svgr/babel-plugin-remove-jsx-attribute/5.4.0: - resolution: {integrity: sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==} - engines: {node: '>=10'} - dev: true - - /@svgr/babel-plugin-remove-jsx-empty-expression/5.0.1: - resolution: {integrity: sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==} - engines: {node: '>=10'} - dev: true - - /@svgr/babel-plugin-replace-jsx-attribute-value/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==} - engines: {node: '>=10'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /@svgr/babel-plugin-svg-dynamic-title/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==} - engines: {node: '>=10'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /@svgr/babel-plugin-svg-em-dimensions/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==} - engines: {node: '>=10'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /@svgr/babel-plugin-transform-react-native-svg/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==} - engines: {node: '>=10'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /@svgr/babel-plugin-transform-svg-component/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==} - engines: {node: '>=12'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /@svgr/babel-preset/6.5.1_@babel+core@7.20.12: - resolution: {integrity: sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==} - engines: {node: '>=10'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@svgr/babel-plugin-add-jsx-attribute': 6.5.1_@babel+core@7.20.12 - '@svgr/babel-plugin-remove-jsx-attribute': 5.4.0 - '@svgr/babel-plugin-remove-jsx-empty-expression': 5.0.1 - '@svgr/babel-plugin-replace-jsx-attribute-value': 6.5.1_@babel+core@7.20.12 - '@svgr/babel-plugin-svg-dynamic-title': 6.5.1_@babel+core@7.20.12 - '@svgr/babel-plugin-svg-em-dimensions': 6.5.1_@babel+core@7.20.12 - '@svgr/babel-plugin-transform-react-native-svg': 6.5.1_@babel+core@7.20.12 - '@svgr/babel-plugin-transform-svg-component': 6.5.1_@babel+core@7.20.12 - dev: true - - /@svgr/core/6.5.1: - resolution: {integrity: sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==} - engines: {node: '>=10'} - dependencies: - '@babel/core': 7.20.12 - '@svgr/babel-preset': 6.5.1_@babel+core@7.20.12 - '@svgr/plugin-jsx': 6.5.1_@svgr+core@6.5.1 - camelcase: 6.3.0 - cosmiconfig: 7.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@svgr/hast-util-to-babel-ast/6.5.1: - resolution: {integrity: sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==} - engines: {node: '>=10'} - dependencies: - '@babel/types': 7.20.7 - entities: 4.4.0 - dev: true - - /@svgr/plugin-jsx/6.5.1_@svgr+core@6.5.1: - resolution: {integrity: sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==} - engines: {node: '>=10'} - peerDependencies: - '@svgr/core': ^6.0.0 - dependencies: - '@babel/core': 7.20.12 - '@svgr/babel-preset': 6.5.1_@babel+core@7.20.12 - '@svgr/core': 6.5.1 - '@svgr/hast-util-to-babel-ast': 6.5.1 - svg-parser: 2.0.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@tanstack/react-table/8.7.6_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-/QijmMFeP7wDLBnr0MQ/5MlbXePbIL/1nOtkxBC9zvmBu4gDKJEDBqipUyM7Wc/iBpSd0IFyqBlvZvTPD9FYDA==} - engines: {node: '>=12'} - peerDependencies: - react: '>=16' - react-dom: '>=16' - dependencies: - '@tanstack/table-core': 8.7.6 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /@tanstack/table-core/8.7.6: - resolution: {integrity: sha512-sqiNTMzB6cpyL8DFH6/VqW48SwiflLqxQqYpo2wNock7rdVGvlm0BLNI8vZUJbr1+fmmWmHwBvi5OMgZw8n1DA==} - engines: {node: '>=12'} - dev: false - - /@testing-library/dom/8.20.0: - resolution: {integrity: sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==} - engines: {node: '>=12'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/runtime': 7.20.7 - '@types/aria-query': 5.0.1 - aria-query: 5.1.3 - chalk: 4.1.2 - dom-accessibility-api: 0.5.15 - lz-string: 1.4.4 - pretty-format: 27.5.1 - dev: true - - /@testing-library/jest-dom/5.16.5: - resolution: {integrity: sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==} - engines: {node: '>=8', npm: '>=6', yarn: '>=1'} - dependencies: - '@adobe/css-tools': 4.0.2 - '@babel/runtime': 7.20.7 - '@types/testing-library__jest-dom': 5.14.5 - aria-query: 5.1.3 - chalk: 3.0.0 - css.escape: 1.5.1 - dom-accessibility-api: 0.5.15 - lodash: 4.17.21 - redent: 3.0.0 - dev: true - - /@testing-library/react-hooks/7.0.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==} - engines: {node: '>=12'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - react-test-renderer: '>=16.9.0' - peerDependenciesMeta: - react-dom: - optional: true - react-test-renderer: - optional: true - dependencies: - '@babel/runtime': 7.20.7 - '@types/react': 17.0.52 - '@types/react-dom': 17.0.18 - '@types/react-test-renderer': 18.0.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-error-boundary: 3.1.4_react@17.0.2 - dev: true - - /@testing-library/react/12.1.5_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==} - engines: {node: '>=12'} - peerDependencies: - react: <18.0.0 - react-dom: <18.0.0 - dependencies: - '@babel/runtime': 7.20.7 - '@testing-library/dom': 8.20.0 - '@types/react-dom': 17.0.18 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: true - - /@testing-library/user-event/13.5.0: - resolution: {integrity: sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==} - engines: {node: '>=10', npm: '>=6'} - peerDependencies: - '@testing-library/dom': '>=7.21.4' - dependencies: - '@babel/runtime': 7.20.7 - dev: true - - /@tootallnate/once/1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - dev: true - - /@tootallnate/once/2.0.0: - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - dev: true - - /@tsconfig/node10/1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - - /@tsconfig/node12/1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14/1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16/1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} - dev: true - - /@types/aria-query/5.0.1: - resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} - dev: true - - /@types/babel__core/7.1.20: - resolution: {integrity: sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==} - dependencies: - '@babel/parser': 7.20.7 - '@babel/types': 7.20.7 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.18.3 - dev: true - - /@types/babel__generator/7.6.4: - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} - dependencies: - '@babel/types': 7.20.7 - dev: true - - /@types/babel__template/7.4.1: - resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} - dependencies: - '@babel/parser': 7.20.7 - '@babel/types': 7.20.7 - dev: true - - /@types/babel__traverse/7.18.3: - resolution: {integrity: sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==} - dependencies: - '@babel/types': 7.20.7 - dev: true - - /@types/body-parser/1.19.2: - resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} - dependencies: - '@types/connect': 3.4.35 - '@types/node': 17.0.45 - dev: true - - /@types/connect/3.4.35: - resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} - dependencies: - '@types/node': 17.0.45 - dev: true - - /@types/d3-array/3.0.4: - resolution: {integrity: sha512-nwvEkG9vYOc0Ic7G7kwgviY4AQlTfYGIZ0fqB7CQHXGyYM6nO7kJh5EguSNA3jfh4rq7Sb7eMVq8isuvg2/miQ==} - dev: false - - /@types/d3-color/3.1.0: - resolution: {integrity: sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==} - dev: false - - /@types/d3-ease/3.0.0: - resolution: {integrity: sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==} - dev: false - - /@types/d3-interpolate/3.0.1: - resolution: {integrity: sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==} - dependencies: - '@types/d3-color': 3.1.0 - dev: false - - /@types/d3-path/3.0.0: - resolution: {integrity: sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==} - dev: false - - /@types/d3-scale/4.0.3: - resolution: {integrity: sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==} - dependencies: - '@types/d3-time': 3.0.0 - dev: false - - /@types/d3-shape/3.1.1: - resolution: {integrity: sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==} - dependencies: - '@types/d3-path': 3.0.0 - dev: false - - /@types/d3-time/3.0.0: - resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==} - dev: false - - /@types/d3-timer/3.0.0: - resolution: {integrity: sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==} - dev: false - - /@types/debug/4.1.7: - resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} - dependencies: - '@types/ms': 0.7.31 - dev: false - - /@types/detect-port/1.3.2: - resolution: {integrity: sha512-xxgAGA2SAU4111QefXPSp5eGbDm/hW6zhvYl9IeEPZEry9F4d66QAHm5qpUXjb6IsevZV/7emAEx5MhP6O192g==} - dev: true - - /@types/diff/5.0.2: - resolution: {integrity: sha512-uw8eYMIReOwstQ0QKF0sICefSy8cNO/v7gOTiIy9SbwuHyEecJUm7qlgueOO5S1udZ5I/irVydHVwMchgzbKTg==} - dev: false - - /@types/doctrine/0.0.3: - resolution: {integrity: sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==} - dev: true - - /@types/ejs/3.1.1: - resolution: {integrity: sha512-RQul5wEfY7BjWm0sYY86cmUN/pcXWGyVxWX93DFFJvcrxax5zKlieLwA3T77xJGwNcZW0YW6CYG70p1m8xPFmA==} - dev: true - - /@types/es-aggregate-error/1.0.2: - resolution: {integrity: sha512-erqUpFXksaeR2kejKnhnjZjbFxUpGZx4Z7ydNL9ie8tEhXPiZTsLeUDJ6aR1F8j5wWUAtOAQWUqkc7givBJbBA==} - dependencies: - '@types/node': 17.0.45 - dev: true - - /@types/escodegen/0.0.6: - resolution: {integrity: sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==} - dev: true - - /@types/estree/0.0.39: - resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} - dev: true - - /@types/estree/0.0.51: - resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} - dev: true - - /@types/estree/1.0.0: - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} - dev: true - - /@types/express-serve-static-core/4.17.33: - resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==} - dependencies: - '@types/node': 17.0.45 - '@types/qs': 6.9.7 - '@types/range-parser': 1.2.4 - dev: true - - /@types/express/4.17.16: - resolution: {integrity: sha512-LkKpqRZ7zqXJuvoELakaFYuETHjZkSol8EV6cNnyishutDBCCdv6+dsKPbKkCcIk57qRphOLY5sEgClw1bO3gA==} - dependencies: - '@types/body-parser': 1.19.2 - '@types/express-serve-static-core': 4.17.33 - '@types/qs': 6.9.7 - '@types/serve-static': 1.15.0 - dev: true - - /@types/find-cache-dir/3.2.1: - resolution: {integrity: sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==} - dev: true - - /@types/flat/5.0.2: - resolution: {integrity: sha512-3zsplnP2djeps5P9OyarTxwRpMLoe5Ash8aL9iprw0JxB+FAHjY+ifn4yZUuW4/9hqtnmor6uvjSRzJhiVbrEQ==} - dev: true - - /@types/glob/7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 17.0.45 - dev: true - - /@types/graceful-fs/4.1.6: - resolution: {integrity: sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==} - dependencies: - '@types/node': 17.0.45 - dev: true - - /@types/hast/2.3.4: - resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /@types/hoist-non-react-statics/3.3.1: - resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} - dependencies: - '@types/react': 17.0.52 - hoist-non-react-statics: 3.3.2 - - /@types/istanbul-lib-coverage/2.0.4: - resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} - dev: true - - /@types/istanbul-lib-report/3.0.0: - resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.4 - dev: true - - /@types/istanbul-reports/3.0.1: - resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} - dependencies: - '@types/istanbul-lib-report': 3.0.0 - dev: true - - /@types/jest/27.5.2: - resolution: {integrity: sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==} - dependencies: - jest-matcher-utils: 27.5.1 - pretty-format: 27.5.1 - dev: true - - /@types/js-cookie/2.2.7: - resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} - dev: false - - /@types/js-yaml/4.0.5: - resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} - dev: true - - /@types/jsdom/20.0.1: - resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} - dependencies: - '@types/node': 17.0.45 - '@types/tough-cookie': 4.0.2 - parse5: 7.1.2 - dev: true - - /@types/json-schema/7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true - - /@types/json5/0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/lodash/4.14.191: - resolution: {integrity: sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==} - - /@types/long/4.0.2: - resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} - dev: false - - /@types/mdast/3.0.10: - resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /@types/mdurl/1.0.2: - resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} - dev: false - - /@types/mdx/2.0.3: - resolution: {integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==} - dev: true - - /@types/mime-types/2.1.1: - resolution: {integrity: sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==} - dev: true - - /@types/mime/3.0.1: - resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} - dev: true - - /@types/minimatch/5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true - - /@types/minimist/1.2.2: - resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: true - - /@types/ms/0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: false - - /@types/node-fetch/2.6.2: - resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} - dependencies: - '@types/node': 17.0.45 - form-data: 3.0.1 - - /@types/node/16.18.11: - resolution: {integrity: sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==} - dev: true - - /@types/node/17.0.45: - resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - - /@types/normalize-package-data/2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true - - /@types/npmlog/4.1.4: - resolution: {integrity: sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==} - dev: true - - /@types/parse-json/4.0.0: - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - - /@types/prettier/2.7.2: - resolution: {integrity: sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==} - dev: true - - /@types/pretty-hrtime/1.0.1: - resolution: {integrity: sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==} - dev: true - - /@types/prop-types/15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} - - /@types/qs/6.9.7: - resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} - dev: true - - /@types/range-parser/1.2.4: - resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} - dev: true - - /@types/react-datepicker/4.8.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-20uzZsIf4moPAjjHDfPvH8UaOHZBxrkiQZoLS3wgKq8Xhp+95gdercLEdoA7/I8nR9R5Jz2qQkdMIM+Lq4AS1A==} - dependencies: - '@popperjs/core': 2.11.6 - '@types/react': 17.0.52 - date-fns: 2.29.3 - react-popper: 2.3.0_vov5yimr6vvxyufd6uigwwkst4 - transitivePeerDependencies: - - react - - react-dom - dev: true - - /@types/react-dom/17.0.18: - resolution: {integrity: sha512-rLVtIfbwyur2iFKykP2w0pl/1unw26b5td16d5xMgp7/yjTHomkyxPYChFoCr/FtEX1lN9wY6lFj1qvKdS5kDw==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react-helmet/6.1.6: - resolution: {integrity: sha512-ZKcoOdW/Tg+kiUbkFCBtvDw0k3nD4HJ/h/B9yWxN4uDO8OkRksWTO+EL+z/Qu3aHTeTll3Ro0Cc/8UhwBCMG5A==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react-lazylog/4.5.1: - resolution: {integrity: sha512-g4yeosa1zYhu2BUJmuu2H2o0dsdRj0o8Omw3pBiVHdLHJaeYIyArvyMRR3bI/MxZxG4EaiRl8AOQ6zeM8P46jA==} - dependencies: - '@types/react': 17.0.52 - immutable: 4.2.2 - dev: true - - /@types/react-paginate/7.1.1: - resolution: {integrity: sha512-94cEJHfBaINba2XGQOWFJF/tYe+AImIhOPqMCfqyeFOgk0qUpDZyDOOW76A1rgdtWndR8UwsMPgV/uuTM8vZ7w==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react-slick/0.23.10: - resolution: {integrity: sha512-ZiqdencANDZy6sWOWJ54LDvebuXFEhDlHtXU9FFipQR2BcYU2QJxZhvJPW6YK7cocibUiNn+YvDTbt1HtCIBVA==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react-table/7.7.14: - resolution: {integrity: sha512-TYrv7onCiakaG1uAu/UpQ9FojNEt/4/ht87EgJQaEGFoWV606ZLWUZAcUHzMxgc3v1mywP1cDyz3qB4ho3hWOw==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react-test-renderer/18.0.0: - resolution: {integrity: sha512-C7/5FBJ3g3sqUahguGi03O79b8afNeSD6T8/GU50oQrJCU0bVCCGQHaGKUbg2Ce8VQEEqTw8/HiS6lXHHdgkdQ==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react-transition-group/4.4.5: - resolution: {integrity: sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==} - dependencies: - '@types/react': 17.0.52 - dev: false - - /@types/react-widgets/4.4.7: - resolution: {integrity: sha512-cW476/b3MOOmZ7kPTx6ShdFWIn54zbgIpsSzwMJVlmr36uDuKeLMjoxoehtYOpFJgpHX9vv24Bfh91Xi9ZQYCA==} - dependencies: - '@types/react': 17.0.52 - dev: true - - /@types/react/17.0.52: - resolution: {integrity: sha512-vwk8QqVODi0VaZZpDXQCmEmiOuyjEFPY7Ttaw5vjM112LOq37yz1CDJGrRJwA1fYEq4Iitd5rnjd1yWAc/bT+A==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.2 - csstype: 3.1.1 - - /@types/sanitize-html/2.8.0: - resolution: {integrity: sha512-Uih6caOm3DsBYnVGOYn0A9NoTNe1c4aPStmHC/YA2JrpP9kx//jzaRcIklFvSpvVQEcpl/ZCr4DgISSf/YxTvg==} - dependencies: - htmlparser2: 8.0.1 - dev: true - - /@types/scheduler/0.16.2: - resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - - /@types/segment-analytics/0.0.34: - resolution: {integrity: sha512-fiOyEgyqJY2Mv9k72WG4XoY4fVE31byiSUrEFcNh+MgHcH3HuJmoz2J7ktO3YizBrN6/RuaH1tY5J/5I5BJHJQ==} - dev: false - - /@types/semver/7.3.13: - resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} - dev: true - - /@types/serve-static/1.15.0: - resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==} - dependencies: - '@types/mime': 3.0.1 - '@types/node': 17.0.45 - dev: true - - /@types/stack-utils/2.0.1: - resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} - dev: true - - /@types/styled-components/5.1.26: - resolution: {integrity: sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==} - dependencies: - '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 17.0.52 - csstype: 3.1.1 - dev: true - - /@types/testing-library__jest-dom/5.14.5: - resolution: {integrity: sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==} - dependencies: - '@types/jest': 27.5.2 - dev: true - - /@types/tough-cookie/4.0.2: - resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==} - dev: true - - /@types/unist/2.0.6: - resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} - - /@types/urijs/1.19.19: - resolution: {integrity: sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg==} - dev: true - - /@types/uuid/9.0.0: - resolution: {integrity: sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==} - dev: false - - /@types/whatwg-streams/0.0.7: - resolution: {integrity: sha512-6sDiSEP6DWcY2ZolsJ2s39ZmsoGQ7KVwBDI3sESQsEm9P2dHTcqnDIHRZFRNtLCzWp7hCFGqYbw5GyfpQnJ01A==} - dev: false - - /@types/yargs-parser/21.0.0: - resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} - dev: true - - /@types/yargs/17.0.19: - resolution: {integrity: sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==} - dependencies: - '@types/yargs-parser': 21.0.0 - dev: true - - /@typescript-eslint/eslint-plugin/5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy: - resolution: {integrity: sha512-sR0Gja9Ky1teIq4qJOl0nC+Tk64/uYdX+mi+5iB//MH8gwyx8e3SOyhEzeLZEFEEfCaLf8KJq+Bd/6je1t+CAg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/parser': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - '@typescript-eslint/scope-manager': 5.48.2 - '@typescript-eslint/type-utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - debug: 4.3.4 - eslint: 8.32.0 - ignore: 5.2.4 - natural-compare-lite: 1.4.0 - regexpp: 3.2.0 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/experimental-utils/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-Iwx8De8dwl6qPaPZWIaEfP1feN/YFlA5FlCxF3zUIm+2AG92C5Tefkugj2L9ytOFrmTYkTE/CqvJFZbYoVZQMg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - eslint: 8.32.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/parser/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-38zMsKsG2sIuM5Oi/olurGwYJXzmtdsHhn5mI/pQogP+BjYVkK5iRazCQ8RGS0V+YLk282uWElN70zAAUmaYHw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.48.2 - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/typescript-estree': 5.48.2_typescript@4.9.5 - debug: 4.3.4 - eslint: 8.32.0 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager/5.48.2: - resolution: {integrity: sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/visitor-keys': 5.48.2 - dev: true - - /@typescript-eslint/type-utils/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 5.48.2_typescript@4.9.5 - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - debug: 4.3.4 - eslint: 8.32.0 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types/5.48.2: - resolution: {integrity: sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/typescript-estree/5.48.2_typescript@4.9.5: - resolution: {integrity: sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/visitor-keys': 5.48.2 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@types/json-schema': 7.0.11 - '@types/semver': 7.3.13 - '@typescript-eslint/scope-manager': 5.48.2 - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/typescript-estree': 5.48.2_typescript@4.9.5 - eslint: 8.32.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.32.0 - semver: 7.3.8 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys/5.48.2: - resolution: {integrity: sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.48.2 - eslint-visitor-keys: 3.3.0 - dev: true - - /@vitejs/plugin-basic-ssl/1.0.1_vite@4.0.4: - resolution: {integrity: sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==} - engines: {node: '>=14.6.0'} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 - dependencies: - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - dev: true - - /@vitejs/plugin-react/3.0.1_vite@4.0.4: - resolution: {integrity: sha512-mx+QvYwIbbpOIJw+hypjnW1lAbKDHtWK5ibkF/V1/oMBu8HU/chb+SnqJDAsLq1+7rGqjktCEomMTM5KShzUKQ==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/plugin-transform-react-jsx-self': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-jsx-source': 7.19.6_@babel+core@7.20.12 - magic-string: 0.27.0 - react-refresh: 0.14.0 - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - transitivePeerDependencies: - - supports-color - dev: true - - /@xobotyi/scrollbar-width/1.9.5: - resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} - dev: false - - /@yarnpkg/esbuild-plugin-pnp/3.0.0-rc.15_esbuild@0.16.17: - resolution: {integrity: sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==} - engines: {node: '>=14.15.0'} - peerDependencies: - esbuild: '>=0.10.0' - dependencies: - esbuild: 0.16.17 - tslib: 2.5.0 - dev: true - - /abab/2.0.6: - resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} - dev: true - - /abbrev/1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true - - /abort-controller/3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - dev: true - - /accepts/1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: true - - /acorn-globals/7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - dependencies: - acorn: 8.8.1 - acorn-walk: 8.2.0 - dev: true - - /acorn-jsx/5.3.2_acorn@7.4.1: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 7.4.1 - dev: true - - /acorn-jsx/5.3.2_acorn@8.8.1: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.8.1 - dev: true - - /acorn-walk/7.2.0: - resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn-walk/8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn/7.4.1: - resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /acorn/8.8.1: - resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /acorn/8.8.2: - resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /address/1.2.2: - resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} - engines: {node: '>= 10.0.0'} - dev: true - - /agent-base/5.1.1: - resolution: {integrity: sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==} - engines: {node: '>= 6.0.0'} - dev: true - - /agent-base/6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /aggregate-error/3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - dev: true - - /ajv-draft-04/1.0.0_ajv@8.12.0: - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: true - - /ajv-errors/3.0.0_ajv@8.12.0: - resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==} - peerDependencies: - ajv: ^8.0.1 - dependencies: - ajv: 8.12.0 - dev: true - - /ajv-formats/2.1.1_ajv@8.12.0: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: true - - /ajv/6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv/8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - - /ansi-align/3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - dependencies: - string-width: 4.2.3 - dev: true - - /ansi-colors/4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes/4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex/5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-regex/6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles/3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - - /ansi-styles/4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /ansi-styles/5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true - - /ansi-styles/6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch/3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - /app-root-dir/1.0.2: - resolution: {integrity: sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==} - dev: true - - /aproba/2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: true - - /are-we-there-yet/2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.0 - dev: true - - /arg/4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /argparse/1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /argparse/2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - /aria-query/5.1.3: - resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - dependencies: - deep-equal: 2.2.0 - dev: true - - /arr-diff/4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - dev: true - - /arr-flatten/1.1.0: - resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} - engines: {node: '>=0.10.0'} - dev: true - - /arr-union/3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - dev: true - - /array-find-index/1.0.2: - resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} - engines: {node: '>=0.10.0'} - dev: true - - /array-flatten/1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: true - - /array-includes/3.1.6: - resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - get-intrinsic: 1.1.3 - is-string: 1.0.7 - dev: true - - /array-union/2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array-unique/0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - dev: true - - /array.prototype.flat/1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - es-shim-unscopables: 1.0.0 - dev: true - - /array.prototype.flatmap/1.3.1: - resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - es-shim-unscopables: 1.0.0 - dev: true - - /array.prototype.tosorted/1.1.1: - resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.1.3 - dev: true - - /arrify/1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true - - /as-table/1.0.55: - resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} - dependencies: - printable-characters: 1.0.42 - dev: true - - /asap/2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - dev: true - - /assert/2.0.0: - resolution: {integrity: sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==} - dependencies: - es6-object-assign: 1.1.0 - is-nan: 1.3.2 - object-is: 1.1.5 - util: 0.12.5 - dev: true - - /assign-symbols/1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - dev: true - - /ast-types-flow/0.0.7: - resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} - dev: true - - /ast-types/0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - dependencies: - tslib: 2.5.0 - dev: true - - /ast-types/0.14.2: - resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} - engines: {node: '>=4'} - dependencies: - tslib: 2.4.1 - dev: true - - /ast-types/0.16.1: - resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} - engines: {node: '>=4'} - dependencies: - tslib: 2.5.0 - dev: true - - /astral-regex/2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true - - /astring/1.8.4: - resolution: {integrity: sha512-97a+l2LBU3Op3bBQEff79i/E4jMD2ZLFD8rHx9B6mXyB2uQwhJQYfiDqUwtfjF4QA1F2qs//N6Cw8LetMbQjcw==} - hasBin: true - dev: true - - /async-limiter/1.0.1: - resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==} - dev: true - - /async/3.2.4: - resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} - dev: true - - /asynckit/0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - /atob/2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} - engines: {node: '>= 4.5.0'} - hasBin: true - dev: true - - /available-typed-arrays/1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true - - /axe-core/4.6.2: - resolution: {integrity: sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==} - engines: {node: '>=4'} - dev: true - - /axobject-query/3.1.1: - resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} - dependencies: - deep-equal: 2.2.0 - dev: true - - /babel-core/7.0.0-bridge.0_@babel+core@7.20.12: - resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - dev: true - - /babel-jest/29.3.1_@babel+core@7.20.12: - resolution: {integrity: sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.20.12 - '@jest/transform': 29.3.1 - '@types/babel__core': 7.1.20 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.2.0_@babel+core@7.20.12 - chalk: 4.1.2 - graceful-fs: 4.2.10 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-istanbul/6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.20.2 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-jest-hoist/29.2.0: - resolution: {integrity: sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/template': 7.20.7 - '@babel/types': 7.20.7 - '@types/babel__core': 7.1.20 - '@types/babel__traverse': 7.18.3 - dev: true - - /babel-plugin-macros/3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - dependencies: - '@babel/runtime': 7.20.7 - cosmiconfig: 7.1.0 - resolve: 1.22.1 - - /babel-plugin-polyfill-corejs2/0.3.3_@babel+core@7.20.12: - resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.20.10 - '@babel/core': 7.20.12 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.12 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-corejs3/0.6.0_@babel+core@7.20.12: - resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.12 - core-js-compat: 3.27.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-regenerator/0.4.1_@babel+core@7.20.12: - resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.20.12 - '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.12 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-styled-components/2.0.7_styled-components@5.3.6: - resolution: {integrity: sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==} - peerDependencies: - styled-components: '>= 2' - dependencies: - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-module-imports': 7.18.6 - babel-plugin-syntax-jsx: 6.18.0 - lodash: 4.17.21 - picomatch: 2.3.1 - styled-components: 5.3.6_sfoxds7t5ydpegc3knd667wn6m - dev: false - - /babel-plugin-syntax-jsx/6.18.0: - resolution: {integrity: sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==} - dev: false - - /babel-plugin-transform-react-remove-prop-types/0.4.24: - resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} - dev: true - - /babel-preset-current-node-syntax/1.0.1_@babel+core@7.20.12: - resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.12 - '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.20.12 - '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.20.12 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.12 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.20.12 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.12 - dev: true - - /babel-preset-jest/29.2.0_@babel+core@7.20.12: - resolution: {integrity: sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.20.12 - babel-plugin-jest-hoist: 29.2.0 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.12 - dev: true - - /babel-preset-react-app/10.0.1: - resolution: {integrity: sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==} - dependencies: - '@babel/core': 7.20.12 - '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-decorators': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-numeric-separator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-optional-chaining': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-proposal-private-methods': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-private-property-in-object': 7.20.5_@babel+core@7.20.12 - '@babel/plugin-transform-flow-strip-types': 7.19.0_@babel+core@7.20.12 - '@babel/plugin-transform-react-display-name': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-runtime': 7.19.6_@babel+core@7.20.12 - '@babel/preset-env': 7.20.2_@babel+core@7.20.12 - '@babel/preset-react': 7.18.6_@babel+core@7.20.12 - '@babel/preset-typescript': 7.18.6_@babel+core@7.20.12 - '@babel/runtime': 7.20.7 - babel-plugin-macros: 3.1.0 - babel-plugin-transform-react-remove-prop-types: 0.4.24 - transitivePeerDependencies: - - supports-color - dev: true - - /backslash/0.2.0: - resolution: {integrity: sha512-Avs+8FUZ1HF/VFP4YWwHQZSGzRPm37ukU1JQYQWijuHhtXdOuAzcZ8PcAzfIw898a8PyBzdn+RtnKA6MzW0X2A==} - dev: true - - /bail/2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: false - - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /balanced-match/2.0.0: - resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} - dev: true - - /base/0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} - dependencies: - cache-base: 1.0.1 - class-utils: 0.3.6 - component-emitter: 1.3.0 - define-property: 1.0.0 - isobject: 3.0.1 - mixin-deep: 1.3.2 - pascalcase: 0.1.1 - dev: true - - /base64-js/1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false - - /better-opn/2.1.1: - resolution: {integrity: sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==} - engines: {node: '>8.0.0'} - dependencies: - open: 7.4.2 - dev: true - - /big-integer/1.6.51: - resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} - engines: {node: '>=0.6'} - - /binary-extensions/2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - - /body-parser/1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.4 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /boxen/5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} - dependencies: - ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - dev: true - - /bplist-parser/0.2.0: - resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} - engines: {node: '>= 5.10.0'} - dependencies: - big-integer: 1.6.51 - dev: true - - /brace-expansion/1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /brace-expansion/2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces/2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - dependencies: - arr-flatten: 1.1.0 - array-unique: 0.3.2 - extend-shallow: 2.0.1 - fill-range: 4.0.0 - isobject: 3.0.1 - repeat-element: 1.1.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /braces/3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - - /broadcast-channel/3.7.0: - resolution: {integrity: sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==} - dependencies: - '@babel/runtime': 7.20.7 - detect-node: 2.1.0 - js-sha3: 0.8.0 - microseconds: 0.2.0 - nano-time: 1.0.0 - oblivious-set: 1.0.0 - rimraf: 3.0.2 - unload: 2.2.0 - dev: false - - /browser-assert/1.2.1: - resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} - dev: true - - /browserslist/4.21.4: - resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001445 - electron-to-chromium: 1.4.284 - node-releases: 2.0.8 - update-browserslist-db: 1.0.10_browserslist@4.21.4 - - /bser/2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - dev: true - - /buffer-crc32/0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: true - - /buffer-from/1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /builtins/1.0.3: - resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} - dev: true - - /bytes/3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - dev: true - - /bytes/3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true - - /c8/7.12.0: - resolution: {integrity: sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==} - engines: {node: '>=10.12.0'} - hasBin: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@istanbuljs/schema': 0.1.3 - find-up: 5.0.0 - foreground-child: 2.0.0 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-report: 3.0.0 - istanbul-reports: 3.1.5 - rimraf: 3.0.2 - test-exclude: 6.0.0 - v8-to-istanbul: 9.0.1 - yargs: 16.2.0 - yargs-parser: 20.2.9 - dev: true - - /cac/6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - dev: true - - /cache-base/1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} - dependencies: - collection-visit: 1.0.0 - component-emitter: 1.3.0 - get-value: 2.0.6 - has-value: 1.0.0 - isobject: 3.0.1 - set-value: 2.0.1 - to-object-path: 0.3.0 - union-value: 1.0.1 - unset-value: 1.0.0 - dev: true - - /call-bind/1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.1.3 - dev: true - - /call-me-maybe/1.0.2: - resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} - dev: true - - /callsites/3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - /camelcase-keys/6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - dev: true - - /camelcase/5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /camelcase/6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /camelize/1.0.1: - resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} - dev: false - - /caniuse-lite/1.0.30001445: - resolution: {integrity: sha512-8sdQIdMztYmzfTMO6KfLny878Ln9c2M0fc7EH60IjlP4Dc4PiCy7K2Vl3ITmWgOyPgVQKa5x+UP/KqFsxj4mBg==} - - /ccount/2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - dev: false - - /chalk/2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - /chalk/3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /chalk/4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /char-regex/1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - dev: true - - /character-entities-html4/2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - dev: false - - /character-entities-legacy/3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - dev: false - - /character-entities/2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - dev: false - - /character-reference-invalid/2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - dev: false - - /chokidar/3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 - - /chownr/2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true - - /ci-info/3.7.1: - resolution: {integrity: sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==} - engines: {node: '>=8'} - dev: true - - /cjs-module-lexer/1.2.2: - resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} - dev: true - - /class-utils/0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-union: 3.1.0 - define-property: 0.2.5 - isobject: 3.0.1 - static-extend: 0.1.2 - dev: true - - /classnames/2.3.2: - resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} - dev: false - - /clean-stack/2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true - - /cli-boxes/2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - dev: true - - /cli-cursor/3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - dependencies: - restore-cursor: 3.1.0 - dev: true - - /cli-table3/0.6.3: - resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} - engines: {node: 10.* || >= 12.*} - dependencies: - string-width: 4.2.3 - optionalDependencies: - '@colors/colors': 1.5.0 - dev: true - - /cli-truncate/2.1.0: - resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} - engines: {node: '>=8'} - dependencies: - slice-ansi: 3.0.0 - string-width: 4.2.3 - dev: true - - /cli-truncate/3.1.0: - resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - slice-ansi: 5.0.0 - string-width: 5.1.2 - dev: true - - /client-only/0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - - /cliui/7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - /cliui/8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /clone-deep/4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - dev: true - - /clone/1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - - /clsx/1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} - dev: false - - /co/4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /collect-v8-coverage/1.0.1: - resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} - dev: true - - /collection-visit/1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} - dependencies: - map-visit: 1.0.0 - object-visit: 1.0.1 - dev: true - - /color-convert/1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - - /color-convert/2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name/1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /color-support/1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: true - - /colord/2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - dev: true - - /colorette/2.0.19: - resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} - dev: true - - /combined-stream/1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - - /comma-separated-tokens/2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - dev: false - - /commander/2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /commander/6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - dev: true - - /commander/8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - - /commander/9.5.0: - resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} - engines: {node: ^12.20.0 || >=14} - dev: true - - /commondir/1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - dev: true - - /compare-versions/4.1.4: - resolution: {integrity: sha512-FemMreK9xNyL8gQevsdRMrvO4lFCkQP7qbuktn1q8ndcNk1+0mz7lgE7b/sNvbhVgY4w6tMN1FDp6aADjqw2rw==} - dev: true - - /component-emitter/1.3.0: - resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} - dev: true - - /compressible/2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /compression/1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /concat-map/0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - /concat-stream/1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.7 - typedarray: 0.0.6 - dev: true - - /confusing-browser-globals/1.0.11: - resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - dev: true - - /console-control-strings/1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: true - - /content-disposition/0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /content-type/1.0.4: - resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==} - engines: {node: '>= 0.6'} - dev: true - - /convert-source-map/1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - - /convert-source-map/2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie-signature/1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: true - - /cookie/0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: true - - /copy-anything/2.0.6: - resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} - dependencies: - is-what: 3.14.1 - dev: true - - /copy-descriptor/0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - dev: true - - /copy-to-clipboard/3.3.3: - resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} - dependencies: - toggle-selection: 1.0.6 - dev: false - - /core-js-compat/3.27.1: - resolution: {integrity: sha512-Dg91JFeCDA17FKnneN7oCMz4BkQ4TcffkgHP4OWwp9yx3pi7ubqMDXXSacfNak1PQqjc95skyt+YBLHQJnkJwA==} - dependencies: - browserslist: 4.21.4 - dev: true - - /core-util-is/1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /cosmiconfig/7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - dependencies: - '@types/parse-json': 4.0.0 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - - /create-require/1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn/7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /crypto-random-string/2.0.0: - resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} - engines: {node: '>=8'} - dev: true - - /css-color-keywords/1.0.0: - resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} - engines: {node: '>=4'} - dev: false - - /css-functions-list/3.1.0: - resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==} - engines: {node: '>=12.22'} - dev: true - - /css-in-js-utils/3.1.0: - resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} - dependencies: - hyphenate-style-name: 1.0.4 - dev: false - - /css-selector-tokenizer/0.7.3: - resolution: {integrity: sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==} - dependencies: - cssesc: 3.0.0 - fastparse: 1.1.2 - dev: true - - /css-to-react-native/3.1.0: - resolution: {integrity: sha512-AryfkFA29b4I3vG7N4kxFboq15DxwSXzhXM37XNEjwJMgjYIc8BcqfiprpAqX0zadI5PMByEIwAMzXxk5Vcc4g==} - dependencies: - camelize: 1.0.1 - css-color-keywords: 1.0.0 - postcss-value-parser: 4.2.0 - dev: false - - /css-tree/1.1.3: - resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} - engines: {node: '>=8.0.0'} - dependencies: - mdn-data: 2.0.14 - source-map: 0.6.1 - dev: false - - /css-unit-converter/1.1.2: - resolution: {integrity: sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==} - dev: false - - /css.escape/1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - dev: true - - /cssesc/3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /cssom/0.3.8: - resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} - dev: true - - /cssom/0.5.0: - resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} - dev: true - - /cssstyle/2.3.0: - resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} - engines: {node: '>=8'} - dependencies: - cssom: 0.3.8 - dev: true - - /csstype/3.1.1: - resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} - - /cuid/2.1.8: - resolution: {integrity: sha512-xiEMER6E7TlTPnDxrM4eRiC6TRgjNX9xzEZ5U/Se2YJKr7Mq4pJn/2XEHjl3STcSh96GmkHPcBXLES8M29wyyg==} - deprecated: Cuid and other k-sortable and non-cryptographic ids (Ulid, ObjectId, KSUID, all UUIDs) are all insecure. Use @paralleldrive/cuid2 instead. - dev: true - - /d3-array/3.2.1: - resolution: {integrity: sha512-gUY/qeHq/yNqqoCKNq4vtpFLdoCdvyNpWoC/KNjhGbhDuQpAM9sIQQKkXSNpXa9h5KySs/gzm7R88WkUutgwWQ==} - engines: {node: '>=12'} - dependencies: - internmap: 2.0.3 - dev: false - - /d3-color/3.1.0: - resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} - engines: {node: '>=12'} - dev: false - - /d3-ease/3.0.1: - resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} - engines: {node: '>=12'} - dev: false - - /d3-format/3.1.0: - resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} - engines: {node: '>=12'} - dev: false - - /d3-interpolate/3.0.1: - resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} - engines: {node: '>=12'} - dependencies: - d3-color: 3.1.0 - dev: false - - /d3-path/3.1.0: - resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} - engines: {node: '>=12'} - dev: false - - /d3-scale/4.0.2: - resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} - engines: {node: '>=12'} - dependencies: - d3-array: 3.2.1 - d3-format: 3.1.0 - d3-interpolate: 3.0.1 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - dev: false - - /d3-shape/3.2.0: - resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} - engines: {node: '>=12'} - dependencies: - d3-path: 3.1.0 - dev: false - - /d3-time-format/4.1.0: - resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} - engines: {node: '>=12'} - dependencies: - d3-time: 3.1.0 - dev: false - - /d3-time/3.1.0: - resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} - engines: {node: '>=12'} - dependencies: - d3-array: 3.2.1 - dev: false - - /d3-timer/3.0.1: - resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} - engines: {node: '>=12'} - dev: false - - /damerau-levenshtein/1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /data-uri-to-buffer/2.0.2: - resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} - dev: true - - /data-uri-to-buffer/3.0.1: - resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} - engines: {node: '>= 6'} - dev: true - - /data-urls/3.0.2: - resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} - engines: {node: '>=12'} - dependencies: - abab: 2.0.6 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - dev: true - - /date-arithmetic/3.1.0: - resolution: {integrity: sha512-ynlmvduDVuzwDDYW3OF4RHCikdzegg0vWQtzwjiVKPs/RjZ93b/7AxIwhfZKxSQQFA8l9lwhkyeDVQyrzbPUwA==} - dev: false - - /date-fns/2.29.3: - resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} - engines: {node: '>=0.11'} - - /dayjs/1.11.7: - resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} - dev: false - - /debug/2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug/3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /debug/4.3.4_supports-color@5.5.0: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - supports-color: 5.5.0 - dev: false - - /debug/4.3.4_supports-color@9.3.1: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - supports-color: 9.3.1 - dev: true - - /debuglog/1.0.1: - resolution: {integrity: sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==} - dev: true - - /decamelize-keys/1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - dev: true - - /decamelize/1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /decimal.js-light/2.5.1: - resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} - dev: false - - /decimal.js/10.4.3: - resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} - dev: true - - /decode-named-character-reference/1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} - dependencies: - character-entities: 2.0.2 - dev: false - - /decode-uri-component/0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - - /dedent/0.7.0: - resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} - dev: true - - /deep-equal/2.2.0: - resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} - dependencies: - call-bind: 1.0.2 - es-get-iterator: 1.1.3 - get-intrinsic: 1.1.3 - is-arguments: 1.1.1 - is-array-buffer: 3.0.1 - is-date-object: 1.0.5 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - isarray: 2.0.5 - object-is: 1.1.5 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.4.3 - side-channel: 1.0.4 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.9 - dev: true - - /deep-is/0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deepmerge/2.2.1: - resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==} - engines: {node: '>=0.10.0'} - - /deepmerge/4.2.2: - resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} - engines: {node: '>=0.10.0'} - - /default-browser-id/3.0.0: - resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} - engines: {node: '>=12'} - dependencies: - bplist-parser: 0.2.0 - untildify: 4.0.0 - dev: true - - /defaults/1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - dependencies: - clone: 1.0.4 - dev: true - - /define-lazy-prop/2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - dev: true - - /define-properties/1.1.4: - resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} - engines: {node: '>= 0.4'} - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: true - - /define-property/0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 0.1.6 - dev: true - - /define-property/1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 1.0.2 - dev: true - - /define-property/2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 1.0.2 - isobject: 3.0.1 - dev: true - - /defu/6.1.2: - resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} - dev: true - - /degenerator/3.0.2: - resolution: {integrity: sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==} - engines: {node: '>= 6'} - dependencies: - ast-types: 0.13.4 - escodegen: 1.14.3 - esprima: 4.0.1 - vm2: 3.9.13 - dev: true - - /del/6.1.1: - resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} - engines: {node: '>=10'} - dependencies: - globby: 11.1.0 - graceful-fs: 4.2.10 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 4.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - dev: true - - /delayed-stream/1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - /delegates/1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: true - - /depd/2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /dependency-graph/0.11.0: - resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} - engines: {node: '>= 0.6.0'} - dev: true - - /dequal/2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - /destroy/1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - - /detect-indent/6.1.0: - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} - engines: {node: '>=8'} - dev: true - - /detect-newline/3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - dev: true - - /detect-node/2.1.0: - resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - dev: false - - /detect-package-manager/2.0.1: - resolution: {integrity: sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==} - engines: {node: '>=12'} - dependencies: - execa: 5.1.1 - dev: true - - /detect-port/1.5.1: - resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} - hasBin: true - dependencies: - address: 1.2.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /dezalgo/1.0.4: - resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} - dependencies: - asap: 2.0.6 - wrappy: 1.0.2 - dev: true - - /diff-sequences/27.5.1: - resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - - /diff-sequences/29.3.1: - resolution: {integrity: sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /diff/4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /diff/5.1.0: - resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} - engines: {node: '>=0.3.1'} - dev: false - - /dir-glob/3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine/2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine/3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dom-accessibility-api/0.5.15: - resolution: {integrity: sha512-8o+oVqLQZoruQPYy3uAAQtc6YbtSiRq5aPJBhJ82YTJRHvI6ofhYAkC81WmjFTnfUbqg6T3aCglIpU9p/5e7Cw==} - dev: true - - /dom-helpers/3.4.0: - resolution: {integrity: sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==} - dependencies: - '@babel/runtime': 7.20.7 - dev: false - - /dom-helpers/5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - dependencies: - '@babel/runtime': 7.20.7 - csstype: 3.1.1 - dev: false - - /dom-serializer/2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.4.0 - - /domelementtype/2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - - /domexception/4.0.0: - resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} - engines: {node: '>=12'} - dependencies: - webidl-conversions: 7.0.0 - dev: true - - /domhandler/5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - - /domutils/3.0.1: - resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - - /dotenv-expand/10.0.0: - resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} - engines: {node: '>=12'} - dev: true - - /dotenv/16.0.3: - resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} - engines: {node: '>=12'} - dev: true - - /eastasianwidth/0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first/1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - - /ejs/3.1.8: - resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.8.5 - dev: true - - /electron-to-chromium/1.4.284: - resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} - - /emittery/0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - dev: true - - /emoji-regex/8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - /emoji-regex/9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl/1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: true - - /enquire.js/2.1.6: - resolution: {integrity: sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==} - dev: false - - /enquirer/2.3.6: - resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - dev: true - - /entities/4.4.0: - resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} - engines: {node: '>=0.12'} - - /envinfo/7.8.1: - resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /eol/0.9.1: - resolution: {integrity: sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==} - dev: true - - /errno/0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} - hasBin: true - requiresBuild: true - dependencies: - prr: 1.0.1 - dev: true - optional: true - - /error-ex/1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - - /error-stack-parser/2.1.4: - resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} - dependencies: - stackframe: 1.3.4 - dev: false - - /es-abstract/1.21.1: - resolution: {integrity: sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 - es-to-primitive: 1.2.1 - function-bind: 1.1.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.1.3 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-proto: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.4 - is-array-buffer: 3.0.1 - is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.10 - is-weakref: 1.0.2 - object-inspect: 1.12.3 - object-keys: 1.1.1 - object.assign: 4.1.4 - regexp.prototype.flags: 1.4.3 - safe-regex-test: 1.0.0 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.9 - dev: true - - /es-aggregate-error/1.0.9: - resolution: {integrity: sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.1.4 - es-abstract: 1.21.1 - function-bind: 1.1.1 - functions-have-names: 1.2.3 - get-intrinsic: 1.2.0 - globalthis: 1.0.3 - has-property-descriptors: 1.0.0 - dev: true - - /es-get-iterator/1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - has-symbols: 1.0.3 - is-arguments: 1.1.1 - is-map: 2.0.2 - is-set: 2.0.2 - is-string: 1.0.7 - isarray: 2.0.5 - stop-iteration-iterator: 1.0.0 - dev: true - - /es-module-lexer/0.9.3: - resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} - dev: true - - /es-set-tostringtag/2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.1.3 - has: 1.0.3 - has-tostringtag: 1.0.0 - dev: true - - /es-shim-unscopables/1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} - dependencies: - has: 1.0.3 - dev: true - - /es-to-primitive/1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /es6-object-assign/1.1.0: - resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==} - dev: true - - /es6-promise/3.3.1: - resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} - dev: true - - /esbuild-android-64/0.15.18: - resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /esbuild-android-arm64/0.15.18: - resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /esbuild-darwin-64/0.15.18: - resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /esbuild-darwin-arm64/0.15.18: - resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /esbuild-freebsd-64/0.15.18: - resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-freebsd-arm64/0.15.18: - resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-32/0.15.18: - resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-64/0.15.18: - resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-arm/0.15.18: - resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-arm64/0.15.18: - resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-mips64le/0.15.18: - resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-ppc64le/0.15.18: - resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-riscv64/0.15.18: - resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-linux-s390x/0.15.18: - resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /esbuild-netbsd-64/0.15.18: - resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-openbsd-64/0.15.18: - resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: true - optional: true - - /esbuild-plugin-alias/0.2.1: - resolution: {integrity: sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==} - dev: true - - /esbuild-register/3.4.2_esbuild@0.16.17: - resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} - peerDependencies: - esbuild: '>=0.12 <1' - dependencies: - debug: 4.3.4 - esbuild: 0.16.17 - transitivePeerDependencies: - - supports-color - dev: true - - /esbuild-sunos-64/0.15.18: - resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-32/0.15.18: - resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-64/0.15.18: - resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild-windows-arm64/0.15.18: - resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /esbuild/0.15.18: - resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.15.18 - '@esbuild/linux-loong64': 0.15.18 - esbuild-android-64: 0.15.18 - esbuild-android-arm64: 0.15.18 - esbuild-darwin-64: 0.15.18 - esbuild-darwin-arm64: 0.15.18 - esbuild-freebsd-64: 0.15.18 - esbuild-freebsd-arm64: 0.15.18 - esbuild-linux-32: 0.15.18 - esbuild-linux-64: 0.15.18 - esbuild-linux-arm: 0.15.18 - esbuild-linux-arm64: 0.15.18 - esbuild-linux-mips64le: 0.15.18 - esbuild-linux-ppc64le: 0.15.18 - esbuild-linux-riscv64: 0.15.18 - esbuild-linux-s390x: 0.15.18 - esbuild-netbsd-64: 0.15.18 - esbuild-openbsd-64: 0.15.18 - esbuild-sunos-64: 0.15.18 - esbuild-windows-32: 0.15.18 - esbuild-windows-64: 0.15.18 - esbuild-windows-arm64: 0.15.18 - dev: true - - /esbuild/0.16.17: - resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.16.17 - '@esbuild/android-arm64': 0.16.17 - '@esbuild/android-x64': 0.16.17 - '@esbuild/darwin-arm64': 0.16.17 - '@esbuild/darwin-x64': 0.16.17 - '@esbuild/freebsd-arm64': 0.16.17 - '@esbuild/freebsd-x64': 0.16.17 - '@esbuild/linux-arm': 0.16.17 - '@esbuild/linux-arm64': 0.16.17 - '@esbuild/linux-ia32': 0.16.17 - '@esbuild/linux-loong64': 0.16.17 - '@esbuild/linux-mips64el': 0.16.17 - '@esbuild/linux-ppc64': 0.16.17 - '@esbuild/linux-riscv64': 0.16.17 - '@esbuild/linux-s390x': 0.16.17 - '@esbuild/linux-x64': 0.16.17 - '@esbuild/netbsd-x64': 0.16.17 - '@esbuild/openbsd-x64': 0.16.17 - '@esbuild/sunos-x64': 0.16.17 - '@esbuild/win32-arm64': 0.16.17 - '@esbuild/win32-ia32': 0.16.17 - '@esbuild/win32-x64': 0.16.17 - dev: true - - /escalade/3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - - /escape-html/1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - - /escape-string-regexp/1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - /escape-string-regexp/2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - dev: true - - /escape-string-regexp/4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - /escape-string-regexp/5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: false - - /escodegen/1.14.3: - resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} - engines: {node: '>=4.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 4.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /escodegen/2.0.0: - resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /eslint-config-prettier/8.6.0_eslint@8.32.0: - resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.32.0 - dev: true - - /eslint-config-react-app/7.0.1_f3p7cdzsbkhsmnshbzhbbdgmve: - resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} - engines: {node: '>=14.0.0'} - peerDependencies: - eslint: ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@babel/core': 7.20.12 - '@babel/eslint-parser': 7.19.1_2je5tsgpdnpnp4f5qs5fqust6m - '@rushstack/eslint-patch': 1.2.0 - '@typescript-eslint/eslint-plugin': 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy - '@typescript-eslint/parser': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - babel-preset-react-app: 10.0.1 - confusing-browser-globals: 1.0.11 - eslint: 8.32.0 - eslint-plugin-flowtype: 8.0.3_eslint@8.32.0 - eslint-plugin-import: 2.27.5_2l6piu6guil2f63lj3qmhzbnn4 - eslint-plugin-jest: 25.7.0_i5clxtuiaceouxhg5syqkw5wwi - eslint-plugin-jsx-a11y: 6.7.1_eslint@8.32.0 - eslint-plugin-react: 7.32.1_eslint@8.32.0 - eslint-plugin-react-hooks: 4.6.0_eslint@8.32.0 - eslint-plugin-testing-library: 5.9.1_et5x32uxl7z5ldub3ye5rhlyqm - typescript: 4.9.5 - transitivePeerDependencies: - - '@babel/plugin-syntax-flow' - - '@babel/plugin-transform-react-jsx' - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /eslint-import-resolver-node/0.3.7: - resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} - dependencies: - debug: 3.2.7 - is-core-module: 2.11.0 - resolve: 1.22.1 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils/2.7.4_kvyj4idustix6trhy5lyssy2sq: - resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - debug: 3.2.7 - eslint: 8.32.0 - eslint-import-resolver-node: 0.3.7 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-css-modules/2.11.0_eslint@8.32.0: - resolution: {integrity: sha512-CLvQvJOMlCywZzaI4HVu7QH/ltgNXvCg7giJGiE+sA9wh5zQ+AqTgftAzrERV22wHe1p688wrU/Zwxt1Ry922w==} - engines: {node: '>=4.0.0'} - peerDependencies: - eslint: '>=2.0.0' - dependencies: - eslint: 8.32.0 - gonzales-pe: 4.3.0 - lodash: 4.17.21 - dev: true - - /eslint-plugin-flowtype/8.0.3_eslint@8.32.0: - resolution: {integrity: sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@babel/plugin-syntax-flow': ^7.14.5 - '@babel/plugin-transform-react-jsx': ^7.14.9 - eslint: ^8.1.0 - dependencies: - eslint: 8.32.0 - lodash: 4.17.21 - string-natural-compare: 3.0.1 - dev: true - - /eslint-plugin-import/2.27.5_2l6piu6guil2f63lj3qmhzbnn4: - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - array-includes: 3.1.6 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.1 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.32.0 - eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4_kvyj4idustix6trhy5lyssy2sq - has: 1.0.3 - is-core-module: 2.11.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.6 - resolve: 1.22.1 - semver: 6.3.0 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest/25.7.0_i5clxtuiaceouxhg5syqkw5wwi: - resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^4.0.0 || ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy - '@typescript-eslint/experimental-utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - eslint: 8.32.0 - jest: 29.3.1_2263m44mchjafa7bz7l52hbcpa - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jest/26.9.0_i5clxtuiaceouxhg5syqkw5wwi: - resolution: {integrity: sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - eslint: 8.32.0 - jest: 29.3.1_2263m44mchjafa7bz7l52hbcpa - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y/6.7.1_eslint@8.32.0: - resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.20.7 - aria-query: 5.1.3 - array-includes: 3.1.6 - array.prototype.flatmap: 1.3.1 - ast-types-flow: 0.0.7 - axe-core: 4.6.2 - axobject-query: 3.1.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 8.32.0 - has: 1.0.3 - jsx-ast-utils: 3.3.3 - language-tags: 1.0.5 - minimatch: 3.1.2 - object.entries: 1.1.6 - object.fromentries: 2.0.6 - semver: 6.3.0 - dev: true - - /eslint-plugin-prettier/4.2.1_cn4lalcyadplruoxa5mhp7j3dq: - resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} - engines: {node: '>=12.0.0'} - peerDependencies: - eslint: '>=7.28.0' - eslint-config-prettier: '*' - prettier: '>=2.0.0' - peerDependenciesMeta: - eslint-config-prettier: - optional: true - dependencies: - eslint: 8.32.0 - eslint-config-prettier: 8.6.0_eslint@8.32.0 - prettier: 2.8.3 - prettier-linter-helpers: 1.0.0 - dev: true - - /eslint-plugin-react-hooks/4.6.0_eslint@8.32.0: - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.32.0 - dev: true - - /eslint-plugin-react/7.32.1_eslint@8.32.0: - resolution: {integrity: sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.6 - array.prototype.flatmap: 1.3.1 - array.prototype.tosorted: 1.1.1 - doctrine: 2.1.0 - eslint: 8.32.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.3 - minimatch: 3.1.2 - object.entries: 1.1.6 - object.fromentries: 2.0.6 - object.hasown: 1.1.2 - object.values: 1.1.6 - prop-types: 15.8.1 - resolve: 2.0.0-next.4 - semver: 6.3.0 - string.prototype.matchall: 4.0.8 - dev: true - - /eslint-plugin-testing-library/5.9.1_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-6BQp3tmb79jLLasPHJmy8DnxREe+2Pgf7L+7o09TSWPfdqqtQfRZmZNetr5mOs3yqZk/MRNxpN3RUpJe0wB4LQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - eslint: 8.32.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-unused-imports/2.0.0_virssgr5omih4ylyae2gddvmxu: - resolution: {integrity: sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy - eslint: 8.32.0 - eslint-rule-composer: 0.3.0 - dev: true - - /eslint-rule-composer/0.3.0: - resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} - engines: {node: '>=4.0.0'} - dev: true - - /eslint-scope/5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope/7.1.1: - resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-utils/3.0.0_eslint@8.32.0: - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.32.0 - eslint-visitor-keys: 2.1.0 - dev: true - - /eslint-visitor-keys/2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys/3.3.0: - resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint/8.32.0: - resolution: {integrity: sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint/eslintrc': 1.4.1 - '@humanwhocodes/config-array': 0.11.8 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.32.0 - eslint-visitor-keys: 3.3.0 - espree: 9.4.1 - esquery: 1.4.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.19.0 - grapheme-splitter: 1.0.4 - ignore: 5.2.4 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-sdsl: 4.3.0 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.1 - regexpp: 3.2.0 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree/9.4.1: - resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.8.1 - acorn-jsx: 5.3.2_acorn@8.8.1 - eslint-visitor-keys: 3.3.0 - dev: true - - /esprima/4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery/1.4.0: - resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse/4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse/4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse/5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /estree-to-babel/3.2.1: - resolution: {integrity: sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==} - engines: {node: '>=8.3.0'} - dependencies: - '@babel/traverse': 7.20.12 - '@babel/types': 7.20.7 - c8: 7.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /estree-walker/1.0.1: - resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} - dev: true - - /estree-walker/2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: true - - /esutils/2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag/1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: true - - /event-target-shim/5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - dev: true - - /eventemitter3/4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: false - - /execa/5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /exit/0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - dev: true - - /expand-brackets/2.1.4: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - dependencies: - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /expect-type/0.14.2: - resolution: {integrity: sha512-ed3+tr5ujbIYXZ8Pl/VgIphwJQ0q5tBLGGdn7Zvwt1WyPBRX83xjT5pT77P/GkuQbctx0K2ZNSSan7eruJqTCQ==} - dev: true - - /expect/29.3.1: - resolution: {integrity: sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.3.1 - jest-get-type: 29.2.0 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-util: 29.3.1 - dev: true - - /express/4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.1 - content-disposition: 0.5.4 - content-type: 1.0.4 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /extend-shallow/2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - dependencies: - is-extendable: 0.1.1 - dev: true - - /extend-shallow/3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} - dependencies: - assign-symbols: 1.0.0 - is-extendable: 1.0.1 - dev: true - - /extend/3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - - /extglob/2.0.4: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - dependencies: - array-unique: 0.3.2 - define-property: 1.0.0 - expand-brackets: 2.1.4 - extend-shallow: 2.0.1 - fragment-cache: 0.2.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /extract-zip/1.7.0: - resolution: {integrity: sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==} - hasBin: true - dependencies: - concat-stream: 1.6.2 - debug: 2.6.9 - mkdirp: 0.5.6 - yauzl: 2.10.0 - transitivePeerDependencies: - - supports-color - dev: true - - /fast-deep-equal/2.0.1: - resolution: {integrity: sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==} - dev: false - - /fast-deep-equal/3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - /fast-diff/1.2.0: - resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - dev: true - - /fast-equals/2.0.4: - resolution: {integrity: sha512-caj/ZmjHljPrZtbzJ3kfH5ia/k4mTJe/qSiXAGzxZWRZgsgDV0cvNaQULqUX8t0/JVlzzEdYOwCN5DmzTxoD4w==} - dev: false - - /fast-glob/3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-glob/3.2.7: - resolution: {integrity: sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==} - engines: {node: '>=8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify/2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein/2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fast-loops/1.1.3: - resolution: {integrity: sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==} - dev: false - - /fast-memoize/2.5.2: - resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} - dev: true - - /fast-safe-stringify/2.1.1: - resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - dev: true - - /fast-shallow-equal/1.0.0: - resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} - dev: false - - /fastest-levenshtein/1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - dev: true - - /fastest-stable-stringify/2.0.2: - resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} - dev: false - - /fastparse/1.1.2: - resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==} - dev: true - - /fastq/1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - dependencies: - reusify: 1.0.4 - dev: true - - /fault/2.0.1: - resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} - dependencies: - format: 0.2.2 - dev: false - - /faye-websocket/0.11.4: - resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} - engines: {node: '>=0.8.0'} - dependencies: - websocket-driver: 0.7.4 - dev: false - - /fb-watchman/2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - dev: true - - /fd-slicer/1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - dependencies: - pend: 1.2.0 - dev: true - - /fetch-readablestream/0.2.0: - resolution: {integrity: sha512-qu4mXWf4wus4idBIN/kVH+XSer8IZ9CwHP+Pd7DL7TuKNC1hP7ykon4kkBjwJF3EMX2WsFp4hH7gU7CyL7ucXw==} - dev: false - - /fetch-retry/5.0.3: - resolution: {integrity: sha512-uJQyMrX5IJZkhoEUBQ3EjxkeiZkppBd5jS/fMTJmfZxLSiaQjv2zD0kTvuvkSH89uFvgSlB6ueGpjD3HWN7Bxw==} - dev: true - - /file-entry-cache/6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.0.4 - dev: true - - /file-system-cache/2.0.2: - resolution: {integrity: sha512-lp4BHO4CWqvRyx88Tt3quZic9ZMf4cJyquYq7UI8sH42Bm2ArlBBjKQAalZOo+UfaBassb7X123Lik5qZ/tSAA==} - dependencies: - fs-extra: 11.1.0 - ramda: 0.28.0 - dev: true - - /file-uri-to-path/2.0.0: - resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==} - engines: {node: '>= 6'} - dev: true - - /filelist/1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: true - - /fill-range/4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - - /filter-obj/1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - dev: false - - /finalhandler/1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /find-cache-dir/2.1.0: - resolution: {integrity: sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==} - engines: {node: '>=6'} - dependencies: - commondir: 1.0.1 - make-dir: 2.1.0 - pkg-dir: 3.0.0 - dev: true - - /find-cache-dir/3.3.2: - resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} - engines: {node: '>=8'} - dependencies: - commondir: 1.0.1 - make-dir: 3.1.0 - pkg-dir: 4.2.0 - dev: true - - /find-root/1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - dev: false - - /find-up/3.0.0: - resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} - engines: {node: '>=6'} - dependencies: - locate-path: 3.0.0 - dev: true - - /find-up/4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up/5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /firebase/9.15.0: - resolution: {integrity: sha512-Fa8qFahDY/pMYMzwPGcfpUkAS3Q55qJ0QKD+5xnXjSX/jVHsJqoXtxapmyDCfAKktiLhXIcRElW1VDVd9xGwQQ==} - dependencies: - '@firebase/analytics': 0.9.0_@firebase+app@0.9.0 - '@firebase/analytics-compat': 0.2.0_5z7svkifsmkn6ro3hru7lnxwrq - '@firebase/app': 0.9.0 - '@firebase/app-check': 0.6.0_@firebase+app@0.9.0 - '@firebase/app-check-compat': 0.3.0_5z7svkifsmkn6ro3hru7lnxwrq - '@firebase/app-compat': 0.2.0 - '@firebase/app-types': 0.9.0 - '@firebase/auth': 0.21.0_@firebase+app@0.9.0 - '@firebase/auth-compat': 0.3.0_z6klzwxqggigirvqix3ggnu6f4 - '@firebase/database': 0.14.0_@firebase+app-types@0.9.0 - '@firebase/database-compat': 0.3.0_@firebase+app-types@0.9.0 - '@firebase/firestore': 3.8.0_@firebase+app@0.9.0 - '@firebase/firestore-compat': 0.3.0_z6klzwxqggigirvqix3ggnu6f4 - '@firebase/functions': 0.9.0_mw76ib4woycgbhoj6pqh7xkrde - '@firebase/functions-compat': 0.3.0_z6klzwxqggigirvqix3ggnu6f4 - '@firebase/installations': 0.6.0_@firebase+app@0.9.0 - '@firebase/installations-compat': 0.2.0_z6klzwxqggigirvqix3ggnu6f4 - '@firebase/messaging': 0.12.0_@firebase+app@0.9.0 - '@firebase/messaging-compat': 0.2.0_5z7svkifsmkn6ro3hru7lnxwrq - '@firebase/performance': 0.6.0_@firebase+app@0.9.0 - '@firebase/performance-compat': 0.2.0_5z7svkifsmkn6ro3hru7lnxwrq - '@firebase/remote-config': 0.4.0_@firebase+app@0.9.0 - '@firebase/remote-config-compat': 0.2.0_5z7svkifsmkn6ro3hru7lnxwrq - '@firebase/storage': 0.10.0_@firebase+app@0.9.0 - '@firebase/storage-compat': 0.2.0_z6klzwxqggigirvqix3ggnu6f4 - '@firebase/util': 1.8.0 - transitivePeerDependencies: - - encoding - dev: false - - /flat-cache/3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.2.7 - rimraf: 3.0.2 - dev: true - - /flat/5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: false - - /flatted/3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - dev: true - - /flow-parser/0.198.2: - resolution: {integrity: sha512-tCQzqXbRAz0ZadIhAXGwdp/xsusADo8IK9idgc/2qCK5RmazbKDGedyykfRtzWgy7Klt4f4NZxq0o/wFUg6plQ==} - engines: {node: '>=0.4.0'} - dev: true - - /for-each/0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /for-in/1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - dev: true - - /foreground-child/2.0.0: - resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} - engines: {node: '>=8.0.0'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 3.0.7 - dev: true - - /form-data/3.0.1: - resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - - /form-data/4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /format-util/1.0.5: - resolution: {integrity: sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==} - dev: true - - /format/0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - dev: false - - /formik/2.2.9_react@17.0.2: - resolution: {integrity: sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==} - peerDependencies: - react: '>=16.8.0' - dependencies: - deepmerge: 2.2.1 - hoist-non-react-statics: 3.3.2 - lodash: 4.17.21 - lodash-es: 4.17.21 - react: 17.0.2 - react-fast-compare: 2.0.4 - tiny-warning: 1.0.3 - tslib: 1.14.1 - dev: false - - /forwarded/0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: true - - /fragment-cache/0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} - dependencies: - map-cache: 0.2.2 - dev: true - - /framer-motion/6.5.1_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==} - peerDependencies: - react: '>=16.8 || ^17.0.0 || ^18.0.0' - react-dom: '>=16.8 || ^17.0.0 || ^18.0.0' - dependencies: - '@motionone/dom': 10.12.0 - framesync: 6.0.1 - hey-listen: 1.0.8 - popmotion: 11.0.3 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - style-value-types: 5.0.0 - tslib: 2.4.1 - optionalDependencies: - '@emotion/is-prop-valid': 0.8.8 - dev: false - - /framesync/6.0.1: - resolution: {integrity: sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==} - dependencies: - tslib: 2.4.1 - dev: false - - /fresh/0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: true - - /fs-extra/10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - dependencies: - graceful-fs: 4.2.10 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: true - - /fs-extra/11.1.0: - resolution: {integrity: sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.10 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: true - - /fs-extra/8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.10 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-minipass/2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: true - - /fs.realpath/1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /fsevents/2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - optional: true - - /ftp/0.3.10: - resolution: {integrity: sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==} - engines: {node: '>=0.8.0'} - dependencies: - readable-stream: 1.1.14 - xregexp: 2.0.0 - dev: true - - /function-bind/1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - - /function.prototype.name/1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names/1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gauge/3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - dev: true - - /generic-names/1.0.3: - resolution: {integrity: sha512-b6OHfQuKasIKM9b6YPkX+KUj/TLBTx3B/1aT1T5F12FEuEqyFMdr59OMS53aoaSw8eVtapdqieX6lbg5opaOhA==} - dependencies: - loader-utils: 3.2.1 - dev: true - - /gensync/1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - /get-caller-file/2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - /get-intrinsic/1.1.3: - resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-symbols: 1.0.3 - dev: true - - /get-intrinsic/1.2.0: - resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-symbols: 1.0.3 - dev: true - - /get-node-dimensions/1.2.1: - resolution: {integrity: sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ==} - dev: false - - /get-package-type/0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - - /get-port/5.1.1: - resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} - engines: {node: '>=8'} - dev: true - - /get-source/2.0.12: - resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} - dependencies: - data-uri-to-buffer: 2.0.2 - source-map: 0.6.1 - dev: true - - /get-stream/6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /get-symbol-description/1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - dev: true - - /get-uri/3.0.2: - resolution: {integrity: sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - data-uri-to-buffer: 3.0.1 - debug: 4.3.4 - file-uri-to-path: 2.0.0 - fs-extra: 8.1.0 - ftp: 0.3.10 - transitivePeerDependencies: - - supports-color - dev: true - - /get-value/2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - dev: true - - /giget/1.0.0: - resolution: {integrity: sha512-KWELZn3Nxq5+0So485poHrFriK9Bn3V/x9y+wgqrHkbmnGbjfLmZ685/SVA/ovW+ewoqW0gVI47pI4yW/VNobQ==} - hasBin: true - dependencies: - colorette: 2.0.19 - defu: 6.1.2 - https-proxy-agent: 5.0.1 - mri: 1.2.0 - node-fetch-native: 1.0.1 - pathe: 1.1.0 - tar: 6.1.13 - transitivePeerDependencies: - - supports-color - dev: true - - /github-slugger/1.5.0: - resolution: {integrity: sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==} - dev: true - - /github-slugger/2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - dev: false - - /glob-parent/5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - - /glob-parent/6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-promise/4.2.2_glob@7.2.3: - resolution: {integrity: sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==} - engines: {node: '>=12'} - peerDependencies: - glob: ^7.1.6 - dependencies: - '@types/glob': 7.2.0 - glob: 7.2.3 - dev: true - - /glob-to-regexp/0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - - /glob/7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /global-modules/2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - dependencies: - global-prefix: 3.0.0 - dev: true - - /global-prefix/3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - dev: true - - /globals/11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - /globals/13.19.0: - resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis/1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.1.4 - dev: true - - /globby/11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.2.12 - ignore: 5.2.4 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globjoin/0.1.4: - resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} - dev: true - - /globrex/0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - dev: true - - /gonzales-pe/4.3.0: - resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==} - engines: {node: '>=0.6.0'} - hasBin: true - dependencies: - minimist: 1.2.7 - dev: true - - /gopd/1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.1.3 - dev: true - - /graceful-fs/4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: true - - /grapheme-splitter/1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true - - /handlebars/4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.7 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.4 - dev: true - - /hard-rejection/2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true - - /has-bigints/1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag/3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - /has-flag/4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors/1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} - dependencies: - get-intrinsic: 1.1.3 - dev: true - - /has-proto/1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols/1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag/1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /has-unicode/2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: true - - /has-value/0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} - dependencies: - get-value: 2.0.6 - has-values: 0.1.4 - isobject: 2.1.0 - dev: true - - /has-value/1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} - dependencies: - get-value: 2.0.6 - has-values: 1.0.0 - isobject: 3.0.1 - dev: true - - /has-values/0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - dev: true - - /has-values/1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - kind-of: 4.0.0 - dev: true - - /has/1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - - /hast-util-has-property/1.0.4: - resolution: {integrity: sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg==} - dev: false - - /hast-util-has-property/2.0.1: - resolution: {integrity: sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==} - dev: false - - /hast-util-heading-rank/2.1.1: - resolution: {integrity: sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==} - dependencies: - '@types/hast': 2.3.4 - dev: false - - /hast-util-to-string/2.0.0: - resolution: {integrity: sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==} - dependencies: - '@types/hast': 2.3.4 - dev: false - - /hast-util-whitespace/2.0.1: - resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} - dev: false - - /hey-listen/1.0.8: - resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} - dev: false - - /history/5.3.0: - resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==} - dependencies: - '@babel/runtime': 7.20.7 - - /hoist-non-react-statics/3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - dependencies: - react-is: 16.13.1 - - /hosted-git-info/2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - - /hosted-git-info/4.1.0: - resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} - engines: {node: '>=10'} - dependencies: - lru-cache: 6.0.0 - dev: true - - /html-encoding-sniffer/3.0.0: - resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} - engines: {node: '>=12'} - dependencies: - whatwg-encoding: 2.0.0 - dev: true - - /html-escaper/2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - - /html-tags/3.2.0: - resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==} - engines: {node: '>=8'} - dev: true - - /htmlparser2/8.0.1: - resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==} - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - domutils: 3.0.1 - entities: 4.4.0 - - /http-errors/2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /http-parser-js/0.5.8: - resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} - dev: false - - /http-proxy-agent/4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /http-proxy-agent/5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 2.0.0 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /http2-client/1.3.5: - resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==} - dev: true - - /https-proxy-agent/4.0.0: - resolution: {integrity: sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==} - engines: {node: '>= 6.0.0'} - dependencies: - agent-base: 5.1.1 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /https-proxy-agent/5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: true - - /human-signals/2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /husky/8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /hyphenate-style-name/1.0.4: - resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} - dev: false - - /ibm-openapi-validator/0.88.3: - resolution: {integrity: sha512-WHkkO5TXWSS12P8VybB04Stq+yFloMlHy2aVzcLAZo425PYIVMuIWhsH7zN9vwcZcOB/qAnWQ4T3PKn6wrcT+Q==} - engines: {node: '>=12.0.0'} - hasBin: true - dependencies: - '@ibm-cloud/openapi-ruleset': 0.37.3 - '@stoplight/spectral-cli': 6.6.0 - '@stoplight/spectral-core': 1.16.0 - '@stoplight/spectral-parsers': 1.0.2 - chalk: 4.1.2 - commander: 2.20.3 - deepmerge: 2.2.1 - find-up: 3.0.0 - globby: 11.1.0 - js-yaml: 3.14.1 - json-dup-key-validator: 1.0.3 - json-schema-ref-parser: 5.1.3 - jsonschema: 1.4.1 - lodash: 4.17.21 - matcher: 1.1.1 - pad: 2.3.0 - require-all: 3.0.0 - semver: 5.7.1 - validator: 13.7.0 - yaml-js: 0.2.3 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /iconv-lite/0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /iconv-lite/0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /icss-utils/3.0.1: - resolution: {integrity: sha512-ANhVLoEfe0KoC9+z4yiTaXOneB49K6JIXdS+yAgH0NERELpdIT7kkj2XxUPuHafeHnn8umXnECSpsfk1RTaUew==} - dependencies: - postcss: 8.4.21 - dev: true - - /icss-utils/5.1.0_postcss@8.4.21: - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.21 - dev: true - - /idb/7.0.1: - resolution: {integrity: sha512-UUxlE7vGWK5RfB/fDwEGgRf84DY/ieqNha6msMV99UsEMQhJ1RwbCd8AYBj3QMgnE3VZnfQvm4oKVCJTYlqIgg==} - dev: false - - /ignore/5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - dev: true - - /image-size/0.5.5: - resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} - engines: {node: '>=0.10.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /immer/9.0.19: - resolution: {integrity: sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==} - dev: true - - /immutable/3.8.2: - resolution: {integrity: sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==} - engines: {node: '>=0.10.0'} - dev: false - - /immutable/4.2.2: - resolution: {integrity: sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==} - - /import-fresh/3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - /import-lazy/4.0.0: - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} - engines: {node: '>=8'} - dev: true - - /import-local/3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - - /imurmurhash/0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /indent-string/4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true - - /inflight/1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits/2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ini/1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - - /inline-style-parser/0.1.1: - resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - dev: false - - /inline-style-prefixer/6.0.4: - resolution: {integrity: sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg==} - dependencies: - css-in-js-utils: 3.1.0 - fast-loops: 1.1.3 - dev: false - - /internal-slot/1.0.4: - resolution: {integrity: sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.1.3 - has: 1.0.3 - side-channel: 1.0.4 - dev: true - - /internmap/2.0.3: - resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} - engines: {node: '>=12'} - dev: false - - /interpret/1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: true - - /intl-messageformat/10.2.5: - resolution: {integrity: sha512-AievYMN6WLLHwBeCTv4aRKG+w3ZNyZtkObwgsKk3Q7GNTq8zDRvDbJSBQkb2OPeVCcAKcIXvak9FF/bRNavoww==} - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - '@formatjs/fast-memoize': 1.2.7 - '@formatjs/icu-messageformat-parser': 2.1.14 - tslib: 2.4.1 - dev: false - - /invariant/2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /ip/1.1.8: - resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} - dev: true - - /ip/2.0.0: - resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} - dev: true - - /ipaddr.js/1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: true - - /is-absolute-url/3.0.3: - resolution: {integrity: sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==} - engines: {node: '>=8'} - dev: true - - /is-accessor-descriptor/0.1.6: - resolution: {integrity: sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-accessor-descriptor/1.0.0: - resolution: {integrity: sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 6.0.3 - dev: true - - /is-alphabetical/2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - dev: false - - /is-alphanumerical/2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - dev: false - - /is-arguments/1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-array-buffer/3.0.1: - resolution: {integrity: sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - is-typed-array: 1.1.10 - dev: true - - /is-arrayish/0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - /is-arrayish/0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - dev: false - - /is-bigint/1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-binary-path/2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - - /is-boolean-object/1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-buffer/1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - dev: true - - /is-buffer/2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - dev: false - - /is-callable/1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module/2.11.0: - resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} - dependencies: - has: 1.0.3 - - /is-data-descriptor/0.1.4: - resolution: {integrity: sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-data-descriptor/1.0.0: - resolution: {integrity: sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 6.0.3 - dev: true - - /is-date-object/1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-decimal/2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - dev: false - - /is-descriptor/0.1.6: - resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} - engines: {node: '>=0.10.0'} - dependencies: - is-accessor-descriptor: 0.1.6 - is-data-descriptor: 0.1.4 - kind-of: 5.1.0 - dev: true - - /is-descriptor/1.0.2: - resolution: {integrity: sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==} - engines: {node: '>=0.10.0'} - dependencies: - is-accessor-descriptor: 1.0.0 - is-data-descriptor: 1.0.0 - kind-of: 6.0.3 - dev: true - - /is-docker/2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-extendable/0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: true - - /is-extendable/1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} - dependencies: - is-plain-object: 2.0.4 - dev: true - - /is-extglob/2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - /is-fullwidth-code-point/3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - /is-fullwidth-code-point/4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - dev: true - - /is-generator-fn/2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - dev: true - - /is-generator-function/1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-glob/4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - - /is-hexadecimal/2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - dev: false - - /is-map/2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - dev: true - - /is-nan/1.3.2: - resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - dev: true - - /is-negative-zero/2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object/1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-number/3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - /is-path-cwd/2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - dev: true - - /is-path-inside/3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-plain-obj/1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true - - /is-plain-obj/4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: false - - /is-plain-object/2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /is-plain-object/5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - - /is-potential-custom-element-name/1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - dev: true - - /is-reference/1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - dependencies: - '@types/estree': 1.0.0 - dev: true - - /is-regex/1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-set/2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - dev: true - - /is-shared-array-buffer/1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.2 - dev: true - - /is-stream/2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-string/1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-symbol/1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array/1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - dev: true - - /is-weakmap/2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - dev: true - - /is-weakref/1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.2 - dev: true - - /is-weakset/2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - dev: true - - /is-what/3.14.1: - resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} - dev: true - - /is-windows/1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true - - /is-wsl/2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - - /isarray/0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - dev: true - - /isarray/1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isarray/2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isexe/2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isobject/2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} - dependencies: - isarray: 1.0.0 - dev: true - - /isobject/3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: true - - /isomorphic-unfetch/3.1.0: - resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} - dependencies: - node-fetch: 2.6.8 - unfetch: 4.2.0 - transitivePeerDependencies: - - encoding - dev: true - - /istanbul-lib-coverage/3.2.0: - resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-instrument/5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.20.12 - '@babel/parser': 7.20.7 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.0 - semver: 6.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-report/3.0.0: - resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} - engines: {node: '>=8'} - dependencies: - istanbul-lib-coverage: 3.2.0 - make-dir: 3.1.0 - supports-color: 7.2.0 - dev: true - - /istanbul-lib-source-maps/4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.4 - istanbul-lib-coverage: 3.2.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-reports/3.1.5: - resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.0 - dev: true - - /jake/10.8.5: - resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.4 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - - /jest-changed-files/29.2.0: - resolution: {integrity: sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - execa: 5.1.1 - p-limit: 3.1.0 - dev: true - - /jest-circus/29.3.1: - resolution: {integrity: sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.3.1 - '@jest/expect': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - chalk: 4.1.2 - co: 4.6.0 - dedent: 0.7.0 - is-generator-fn: 2.1.0 - jest-each: 29.3.1 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-runtime: 29.3.1 - jest-snapshot: 29.3.1 - jest-util: 29.3.1 - p-limit: 3.1.0 - pretty-format: 29.3.1 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-cli/29.3.1_2263m44mchjafa7bz7l52hbcpa: - resolution: {integrity: sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.3.1_ts-node@10.9.1 - '@jest/test-result': 29.3.1 - '@jest/types': 29.3.1 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.10 - import-local: 3.1.0 - jest-config: 29.3.1_2263m44mchjafa7bz7l52hbcpa - jest-util: 29.3.1 - jest-validate: 29.3.1 - prompts: 2.4.2 - yargs: 17.6.2 - transitivePeerDependencies: - - '@types/node' - - supports-color - - ts-node - dev: true - - /jest-config/29.3.1_2263m44mchjafa7bz7l52hbcpa: - resolution: {integrity: sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - dependencies: - '@babel/core': 7.20.12 - '@jest/test-sequencer': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - babel-jest: 29.3.1_@babel+core@7.20.12 - chalk: 4.1.2 - ci-info: 3.7.1 - deepmerge: 4.2.2 - glob: 7.2.3 - graceful-fs: 4.2.10 - jest-circus: 29.3.1 - jest-environment-node: 29.3.1 - jest-get-type: 29.2.0 - jest-regex-util: 29.2.0 - jest-resolve: 29.3.1 - jest-runner: 29.3.1 - jest-util: 29.3.1 - jest-validate: 29.3.1 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.3.1 - slash: 3.0.0 - strip-json-comments: 3.1.1 - ts-node: 10.9.1_cin3sed6ohfsopbmt6orxeb4o4 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-diff/27.5.1: - resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 27.5.1 - jest-get-type: 27.5.1 - pretty-format: 27.5.1 - dev: true - - /jest-diff/29.3.1: - resolution: {integrity: sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.3.1 - jest-get-type: 29.2.0 - pretty-format: 29.3.1 - dev: true - - /jest-docblock/29.2.0: - resolution: {integrity: sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - detect-newline: 3.1.0 - dev: true - - /jest-each/29.3.1: - resolution: {integrity: sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - chalk: 4.1.2 - jest-get-type: 29.2.0 - jest-util: 29.3.1 - pretty-format: 29.3.1 - dev: true - - /jest-environment-jsdom/29.3.1: - resolution: {integrity: sha512-G46nKgiez2Gy4zvYNhayfMEAFlVHhWfncqvqS6yCd0i+a4NsSUD2WtrKSaYQrYiLQaupHXxCRi8xxVL2M9PbhA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - '@jest/environment': 29.3.1 - '@jest/fake-timers': 29.3.1 - '@jest/types': 29.3.1 - '@types/jsdom': 20.0.1 - '@types/node': 17.0.45 - jest-mock: 29.3.1 - jest-util: 29.3.1 - jsdom: 20.0.3 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jest-environment-node/29.3.1: - resolution: {integrity: sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.3.1 - '@jest/fake-timers': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - jest-mock: 29.3.1 - jest-util: 29.3.1 - dev: true - - /jest-get-type/27.5.1: - resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dev: true - - /jest-get-type/29.2.0: - resolution: {integrity: sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-haste-map/29.3.1: - resolution: {integrity: sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - '@types/graceful-fs': 4.1.6 - '@types/node': 17.0.45 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.10 - jest-regex-util: 29.2.0 - jest-util: 29.3.1 - jest-worker: 29.3.1 - micromatch: 4.0.5 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /jest-leak-detector/29.3.1: - resolution: {integrity: sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.2.0 - pretty-format: 29.3.1 - dev: true - - /jest-matcher-utils/27.5.1: - resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 27.5.1 - jest-get-type: 27.5.1 - pretty-format: 27.5.1 - dev: true - - /jest-matcher-utils/29.3.1: - resolution: {integrity: sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.3.1 - jest-get-type: 29.2.0 - pretty-format: 29.3.1 - dev: true - - /jest-message-util/29.3.1: - resolution: {integrity: sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.18.6 - '@jest/types': 29.3.1 - '@types/stack-utils': 2.0.1 - chalk: 4.1.2 - graceful-fs: 4.2.10 - micromatch: 4.0.5 - pretty-format: 29.3.1 - slash: 3.0.0 - stack-utils: 2.0.6 - dev: true - - /jest-mock/29.3.1: - resolution: {integrity: sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - jest-util: 29.3.1 - dev: true - - /jest-pnp-resolver/1.2.3_jest-resolve@29.3.1: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 29.3.1 - dev: true - - /jest-regex-util/29.2.0: - resolution: {integrity: sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-resolve-dependencies/29.3.1: - resolution: {integrity: sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.2.0 - jest-snapshot: 29.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-resolve/29.3.1: - resolution: {integrity: sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 - jest-pnp-resolver: 1.2.3_jest-resolve@29.3.1 - jest-util: 29.3.1 - jest-validate: 29.3.1 - resolve: 1.22.1 - resolve.exports: 1.1.1 - slash: 3.0.0 - dev: true - - /jest-runner/29.3.1: - resolution: {integrity: sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.3.1 - '@jest/environment': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.10 - jest-docblock: 29.2.0 - jest-environment-node: 29.3.1 - jest-haste-map: 29.3.1 - jest-leak-detector: 29.3.1 - jest-message-util: 29.3.1 - jest-resolve: 29.3.1 - jest-runtime: 29.3.1 - jest-util: 29.3.1 - jest-watcher: 29.3.1 - jest-worker: 29.3.1 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-runtime/29.3.1: - resolution: {integrity: sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.3.1 - '@jest/fake-timers': 29.3.1 - '@jest/globals': 29.3.1 - '@jest/source-map': 29.2.0 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - chalk: 4.1.2 - cjs-module-lexer: 1.2.2 - collect-v8-coverage: 1.0.1 - glob: 7.2.3 - graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 - jest-message-util: 29.3.1 - jest-mock: 29.3.1 - jest-regex-util: 29.2.0 - jest-resolve: 29.3.1 - jest-snapshot: 29.3.1 - jest-util: 29.3.1 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-snapshot/29.3.1: - resolution: {integrity: sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.20.12 - '@babel/generator': 7.20.7 - '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12 - '@babel/traverse': 7.20.12 - '@babel/types': 7.20.7 - '@jest/expect-utils': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/babel__traverse': 7.18.3 - '@types/prettier': 2.7.2 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.12 - chalk: 4.1.2 - expect: 29.3.1 - graceful-fs: 4.2.10 - jest-diff: 29.3.1 - jest-get-type: 29.2.0 - jest-haste-map: 29.3.1 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-util: 29.3.1 - natural-compare: 1.4.0 - pretty-format: 29.3.1 - semver: 7.3.8 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-util/29.3.1: - resolution: {integrity: sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - chalk: 4.1.2 - ci-info: 3.7.1 - graceful-fs: 4.2.10 - picomatch: 2.3.1 - dev: true - - /jest-validate/29.3.1: - resolution: {integrity: sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.3.1 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.2.0 - leven: 3.1.0 - pretty-format: 29.3.1 - dev: true - - /jest-watcher/29.3.1: - resolution: {integrity: sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 17.0.45 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.3.1 - string-length: 4.0.2 - dev: true - - /jest-worker/29.3.1: - resolution: {integrity: sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 17.0.45 - jest-util: 29.3.1 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jest/29.3.1_2263m44mchjafa7bz7l52hbcpa: - resolution: {integrity: sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.3.1_ts-node@10.9.1 - '@jest/types': 29.3.1 - import-local: 3.1.0 - jest-cli: 29.3.1_2263m44mchjafa7bz7l52hbcpa - transitivePeerDependencies: - - '@types/node' - - supports-color - - ts-node - dev: true - - /js-cookie/2.2.1: - resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} - dev: false - - /js-sdsl/4.3.0: - resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==} - dev: true - - /js-sha3/0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - dev: false - - /js-tokens/4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /js-yaml/3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /js-yaml/4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - - /jscodeshift/0.13.1_@babel+preset-env@7.20.2: - resolution: {integrity: sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==} - hasBin: true - peerDependencies: - '@babel/preset-env': ^7.1.6 - dependencies: - '@babel/core': 7.20.12 - '@babel/parser': 7.20.7 - '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-proposal-optional-chaining': 7.20.7_@babel+core@7.20.12 - '@babel/plugin-transform-modules-commonjs': 7.20.11_@babel+core@7.20.12 - '@babel/preset-env': 7.20.2_@babel+core@7.20.12 - '@babel/preset-flow': 7.18.6_@babel+core@7.20.12 - '@babel/preset-typescript': 7.18.6_@babel+core@7.20.12 - '@babel/register': 7.18.9_@babel+core@7.20.12 - babel-core: 7.0.0-bridge.0_@babel+core@7.20.12 - chalk: 4.1.2 - flow-parser: 0.198.2 - graceful-fs: 4.2.10 - micromatch: 3.1.10 - neo-async: 2.6.2 - node-dir: 0.1.17 - recast: 0.20.5 - temp: 0.8.4 - write-file-atomic: 2.4.3 - transitivePeerDependencies: - - supports-color - dev: true - - /jsdom/20.0.3: - resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} - engines: {node: '>=14'} - peerDependencies: - canvas: ^2.5.0 - peerDependenciesMeta: - canvas: - optional: true - dependencies: - abab: 2.0.6 - acorn: 8.8.1 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 - decimal.js: 10.4.3 - domexception: 4.0.0 - escodegen: 2.0.0 - form-data: 4.0.0 - html-encoding-sniffer: 3.0.0 - http-proxy-agent: 5.0.0 - https-proxy-agent: 5.0.1 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.2 - parse5: 7.1.2 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 4.1.2 - w3c-xmlserializer: 4.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 2.0.0 - whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - ws: 8.12.0 - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /jsep/1.3.8: - resolution: {integrity: sha512-qofGylTGgYj9gZFsHuyWAN4jr35eJ66qJCK4eKDnldohuUoQFbU3iZn2zjvEbd9wOAhP9Wx5DsAAduTyE1PSWQ==} - engines: {node: '>= 10.16.0'} - dev: true - - /jsesc/0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc/2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - - /json-dup-key-validator/1.0.3: - resolution: {integrity: sha512-JvJcV01JSiO7LRz7DY1Fpzn4wX2rJ3dfNTiAfnlvLNdhhnm0Pgdvhi2SGpENrZn7eSg26Ps3TPhOcuD/a4STXQ==} - dependencies: - backslash: 0.2.0 - dev: true - - /json-parse-even-better-errors/2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - /json-schema-ref-parser/5.1.3: - resolution: {integrity: sha512-CpDFlBwz/6la78hZxyB9FECVKGYjIIl3Ms3KLqFj99W7IIb7D00/RDgc++IGB4BBALl0QRhh5m4q5WNSopvLtQ==} - deprecated: Please switch to @apidevtools/json-schema-ref-parser - dependencies: - call-me-maybe: 1.0.2 - debug: 3.2.7 - js-yaml: 3.14.1 - ono: 4.0.11 - transitivePeerDependencies: - - supports-color - dev: true - - /json-schema-traverse/0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse/1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json-schema/0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - dev: false - - /json-stable-stringify-without-jsonify/1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json2mq/0.2.0: - resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} - dependencies: - string-convert: 0.2.1 - dev: false - - /json5/1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.7 - dev: true - - /json5/2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - /jsonc-parser/2.2.1: - resolution: {integrity: sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==} - dev: true - - /jsonfile/4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.10 - dev: true - - /jsonfile/6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.0 - optionalDependencies: - graceful-fs: 4.2.10 - dev: true - - /jsonpath-plus/6.0.1: - resolution: {integrity: sha512-EvGovdvau6FyLexFH2OeXfIITlgIbgZoAZe3usiySeaIDm5QS+A10DKNpaPBBqqRSZr2HN6HVNXxtwUAr2apEw==} - engines: {node: '>=10.0.0'} - requiresBuild: true - dev: true - optional: true - - /jsonpath-plus/7.1.0: - resolution: {integrity: sha512-gTaNRsPWO/K2KY6MrqaUFClF9kmuM6MFH5Dhg1VYDODgFbByw1yb7xu3hrViE/sz+dGOeMWgCzwUwQtAnCTE9g==} - engines: {node: '>=12.0.0'} - dev: true - - /jsonpointer/5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} - dev: true - - /jsonschema/1.4.1: - resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} - dev: true - - /jsx-ast-utils/3.3.3: - resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.6 - object.assign: 4.1.4 - dev: true - - /kind-of/3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - dev: true - - /kind-of/4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - dev: true - - /kind-of/5.1.0: - resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} - engines: {node: '>=0.10.0'} - dev: true - - /kind-of/6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /kleur/3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /kleur/4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: false - - /known-css-properties/0.26.0: - resolution: {integrity: sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==} - dev: true - - /language-subtag-registry/0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - dev: true - - /language-tags/1.0.5: - resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==} - dependencies: - language-subtag-registry: 0.3.22 - dev: true - - /launchdarkly-js-client-sdk/3.1.0: - resolution: {integrity: sha512-8aM3Wp5ZAS/TCIELOYkEs4CFzih/g7sO+YCHNQ5g0k80WDMTmTcGLMLhCKmrzaQnMK21HiBwbkBpAYnyzr5yUQ==} - dependencies: - escape-string-regexp: 4.0.0 - launchdarkly-js-sdk-common: 5.0.1 - dev: false - - /launchdarkly-js-sdk-common/5.0.1: - resolution: {integrity: sha512-NPPU/9bT4hUCbglCCMAm9XGDWnRKs3aJ1OMhRF8g6xTUWAjOO2FieoGjwVbUVvOYKIiINVVtAWUiuVYbix1lqw==} - dependencies: - base64-js: 1.5.1 - fast-deep-equal: 2.0.1 - uuid: 8.3.2 - dev: false - - /lazy-universal-dotenv/4.0.0: - resolution: {integrity: sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==} - engines: {node: '>=14.0.0'} - dependencies: - app-root-dir: 1.0.2 - dotenv: 16.0.3 - dotenv-expand: 10.0.0 - dev: true - - /less/4.1.3: - resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} - engines: {node: '>=6'} - hasBin: true - dependencies: - copy-anything: 2.0.6 - parse-node-version: 1.0.1 - tslib: 2.5.0 - optionalDependencies: - errno: 0.1.8 - graceful-fs: 4.2.10 - image-size: 0.5.5 - make-dir: 2.1.0 - mime: 1.6.0 - needle: 3.2.0 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /leven/3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /levn/0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - dev: true - - /levn/0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /license-checker/25.0.1: - resolution: {integrity: sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g==} - hasBin: true - dependencies: - chalk: 2.4.2 - debug: 3.2.7 - mkdirp: 0.5.6 - nopt: 4.0.3 - read-installed: 4.0.3 - semver: 5.7.1 - spdx-correct: 3.1.1 - spdx-expression-parse: 3.0.1 - spdx-satisfies: 4.0.1 - treeify: 1.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /lilconfig/2.0.5: - resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} - engines: {node: '>=10'} - dev: true - - /lines-and-columns/1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - /lint-staged/12.5.0: - resolution: {integrity: sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dependencies: - cli-truncate: 3.1.0 - colorette: 2.0.19 - commander: 9.5.0 - debug: 4.3.4_supports-color@9.3.1 - execa: 5.1.1 - lilconfig: 2.0.5 - listr2: 4.0.5 - micromatch: 4.0.5 - normalize-path: 3.0.0 - object-inspect: 1.12.3 - pidtree: 0.5.0 - string-argv: 0.3.1 - supports-color: 9.3.1 - yaml: 1.10.2 - transitivePeerDependencies: - - enquirer - dev: true - - /listr2/4.0.5: - resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} - engines: {node: '>=12'} - peerDependencies: - enquirer: '>= 2.3.0 < 3' - peerDependenciesMeta: - enquirer: - optional: true - dependencies: - cli-truncate: 2.1.0 - colorette: 2.0.19 - log-update: 4.0.0 - p-map: 4.0.0 - rfdc: 1.3.0 - rxjs: 7.8.0 - through: 2.3.8 - wrap-ansi: 7.0.0 - dev: true - - /loader-utils/3.2.1: - resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==} - engines: {node: '>= 12.13.0'} - dev: true - - /locate-path/3.0.0: - resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} - engines: {node: '>=6'} - dependencies: - p-locate: 3.0.0 - path-exists: 3.0.0 - dev: true - - /locate-path/5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path/6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash-es/4.17.21: - resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} - dev: false - - /lodash.camelcase/4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - /lodash.debounce/4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - - /lodash.get/4.4.2: - resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: true - - /lodash.isempty/4.4.0: - resolution: {integrity: sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==} - dev: true - - /lodash.merge/4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.omit/4.5.0: - resolution: {integrity: sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==} - dev: true - - /lodash.omitby/4.6.0: - resolution: {integrity: sha512-5OrRcIVR75M288p4nbI2WLAf3ndw2GD9fyNv3Bc15+WCxJDdZ4lYndSxGd7hnG6PVjiJTeJE2dHEGhIuKGicIQ==} - dev: true - - /lodash.pick/4.4.0: - resolution: {integrity: sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==} - dev: true - - /lodash.throttle/4.1.1: - resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} - dev: false - - /lodash.topath/4.5.2: - resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==} - dev: true - - /lodash.truncate/4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true - - /lodash.uniq/4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - dev: true - - /lodash.uniqby/4.7.0: - resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} - dev: true - - /lodash.uniqwith/4.5.0: - resolution: {integrity: sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==} - dev: true - - /lodash/4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - /log-update/4.0.0: - resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} - engines: {node: '>=10'} - dependencies: - ansi-escapes: 4.3.2 - cli-cursor: 3.1.0 - slice-ansi: 4.0.0 - wrap-ansi: 6.2.0 - dev: true - - /long/4.0.0: - resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} - dev: false - - /long/5.2.1: - resolution: {integrity: sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==} - dev: false - - /longest-streak/3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - dev: false - - /loose-envify/1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - - /lru-cache/5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - - /lru-cache/6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /lz-string/1.4.4: - resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} - hasBin: true - dev: true - - /magic-string/0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - dependencies: - sourcemap-codec: 1.4.8 - dev: true - - /magic-string/0.27.0: - resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /make-dir/2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - dependencies: - pify: 4.0.1 - semver: 5.7.1 - dev: true - - /make-dir/3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - dependencies: - semver: 6.3.0 - dev: true - - /make-error/1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /makeerror/1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - dev: true - - /map-cache/0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-obj/1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-obj/4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true - - /map-or-similar/1.5.0: - resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} - dev: true - - /map-visit/1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} - dependencies: - object-visit: 1.0.1 - dev: true - - /markdown-table/3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} - dev: false - - /markdown-to-jsx/7.1.8_react@17.0.2: - resolution: {integrity: sha512-rRSa1aFmFnpDRFAhv5vIkWM4nPaoB9vnzIjuIKa1wGupfn2hdCNeaQHKpu4/muoc8n8J7yowjTP2oncA4/Rbgg==} - engines: {node: '>= 10'} - peerDependencies: - react: '>= 0.14.0' - dependencies: - react: 17.0.2 - dev: true - - /match-sorter/6.3.1: - resolution: {integrity: sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==} - dependencies: - '@babel/runtime': 7.20.7 - remove-accents: 0.4.2 - dev: false - - /matcher/1.1.1: - resolution: {integrity: sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==} - engines: {node: '>=4'} - dependencies: - escape-string-regexp: 1.0.5 - dev: true - - /mathml-tag-names/2.1.3: - resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} - dev: true - - /mdast-util-definitions/4.0.0: - resolution: {integrity: sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==} - dependencies: - unist-util-visit: 2.0.3 - dev: true - - /mdast-util-definitions/5.1.1: - resolution: {integrity: sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - unist-util-visit: 4.1.1 - dev: false - - /mdast-util-directive/2.2.2: - resolution: {integrity: sha512-6BuW4dFkCbTIf9peVMXdtWylI6ovMidVjnHyJpx7IDhwk3GosIgUs87Rl3x6T6kP5iAf1qIE3lMn6CgWw40d+g==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - mdast-util-to-markdown: 1.5.0 - parse-entities: 4.0.0 - stringify-entities: 4.0.3 - unist-util-visit-parents: 5.1.1 - dev: false - - /mdast-util-find-and-replace/2.2.1: - resolution: {integrity: sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw==} - dependencies: - escape-string-regexp: 5.0.0 - unist-util-is: 5.1.1 - unist-util-visit-parents: 5.1.1 - dev: false - - /mdast-util-from-markdown/1.2.0: - resolution: {integrity: sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - decode-named-character-reference: 1.0.2 - mdast-util-to-string: 3.1.0 - micromark: 3.1.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-decode-string: 1.0.2 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - unist-util-stringify-position: 3.0.2 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-frontmatter/1.0.0: - resolution: {integrity: sha512-7itKvp0arEVNpCktOET/eLFAYaZ+0cNjVtFtIPxgQ5tV+3i+D4SDDTjTzPWl44LT59PC+xdx+glNTawBdF98Mw==} - dependencies: - micromark-extension-frontmatter: 1.0.0 - dev: false - - /mdast-util-gfm-autolink-literal/1.0.2: - resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==} - dependencies: - '@types/mdast': 3.0.10 - ccount: 2.0.1 - mdast-util-find-and-replace: 2.2.1 - micromark-util-character: 1.1.0 - dev: false - - /mdast-util-gfm-footnote/1.0.1: - resolution: {integrity: sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-to-markdown: 1.5.0 - micromark-util-normalize-identifier: 1.0.0 - dev: false - - /mdast-util-gfm-strikethrough/1.0.2: - resolution: {integrity: sha512-T/4DVHXcujH6jx1yqpcAYYwd+z5lAYMw4Ls6yhTfbMMtCt0PHY4gEfhW9+lKsLBtyhUGKRIzcUA2FATVqnvPDA==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-to-markdown: 1.5.0 - dev: false - - /mdast-util-gfm-table/1.0.6: - resolution: {integrity: sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag==} - dependencies: - '@types/mdast': 3.0.10 - markdown-table: 3.0.3 - mdast-util-from-markdown: 1.2.0 - mdast-util-to-markdown: 1.5.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-gfm-task-list-item/1.0.1: - resolution: {integrity: sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-to-markdown: 1.5.0 - dev: false - - /mdast-util-gfm/2.0.1: - resolution: {integrity: sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ==} - dependencies: - mdast-util-from-markdown: 1.2.0 - mdast-util-gfm-autolink-literal: 1.0.2 - mdast-util-gfm-footnote: 1.0.1 - mdast-util-gfm-strikethrough: 1.0.2 - mdast-util-gfm-table: 1.0.6 - mdast-util-gfm-task-list-item: 1.0.1 - mdast-util-to-markdown: 1.5.0 - transitivePeerDependencies: - - supports-color - dev: false - - /mdast-util-phrasing/3.0.0: - resolution: {integrity: sha512-S+QYsDRLkGi8U7o5JF1agKa/sdP+CNGXXLqC17pdTVL8FHHgQEiwFGa9yE5aYtUxNiFGYoaDy9V1kC85Sz86Gg==} - dependencies: - '@types/mdast': 3.0.10 - unist-util-is: 5.1.1 - dev: false - - /mdast-util-to-hast/11.3.0: - resolution: {integrity: sha512-4o3Cli3hXPmm1LhB+6rqhfsIUBjnKFlIUZvudaermXB+4/KONdd/W4saWWkC+LBLbPMqhFSSTSRgafHsT5fVJw==} - dependencies: - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - '@types/mdurl': 1.0.2 - mdast-util-definitions: 5.1.1 - mdurl: 1.0.1 - unist-builder: 3.0.0 - unist-util-generated: 2.0.0 - unist-util-position: 4.0.3 - unist-util-visit: 4.1.1 - dev: false - - /mdast-util-to-markdown/1.5.0: - resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} - dependencies: - '@types/mdast': 3.0.10 - '@types/unist': 2.0.6 - longest-streak: 3.1.0 - mdast-util-phrasing: 3.0.0 - mdast-util-to-string: 3.1.0 - micromark-util-decode-string: 1.0.2 - unist-util-visit: 4.1.1 - zwitch: 2.0.4 - dev: false - - /mdast-util-to-string/1.1.0: - resolution: {integrity: sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==} - dev: true - - /mdast-util-to-string/3.1.0: - resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==} - dev: false - - /mdn-data/2.0.14: - resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - dev: false - - /mdurl/1.0.1: - resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} - dev: false - - /media-typer/0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: true - - /memoize-one/6.0.0: - resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} - dev: false - - /memoizerific/1.11.3: - resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} - dependencies: - map-or-similar: 1.5.0 - dev: true - - /meow/9.0.0: - resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} - engines: {node: '>=10'} - dependencies: - '@types/minimist': 1.2.2 - camelcase-keys: 6.2.2 - decamelize: 1.2.0 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 3.0.3 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.18.1 - yargs-parser: 20.2.9 - dev: true - - /merge-descriptors/1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: true - - /merge-stream/2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2/1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /methods/1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: true - - /micromark-core-commonmark/1.0.6: - resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-factory-destination: 1.0.0 - micromark-factory-label: 1.0.2 - micromark-factory-space: 1.0.0 - micromark-factory-title: 1.0.2 - micromark-factory-whitespace: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-chunked: 1.0.0 - micromark-util-classify-character: 1.0.0 - micromark-util-html-tag-name: 1.1.0 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-subtokenize: 1.0.2 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-directive/2.1.2: - resolution: {integrity: sha512-brqLEztt14/73snVXYsq9Cv6ng67O+Sy69ZuM0s8ZhN/GFI9rnyXyj0Y0DaCwi648vCImv7/U1H5TzR7wMv5jw==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-factory-whitespace: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - parse-entities: 4.0.0 - uvu: 0.5.6 - dev: false - - /micromark-extension-frontmatter/1.0.0: - resolution: {integrity: sha512-EXjmRnupoX6yYuUJSQhrQ9ggK0iQtQlpi6xeJzVD5xscyAI+giqco5fdymayZhJMbIFecjnE2yz85S9NzIgQpg==} - dependencies: - fault: 2.0.1 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-extension-gfm-autolink-literal/1.0.3: - resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-footnote/1.0.4: - resolution: {integrity: sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg==} - dependencies: - micromark-core-commonmark: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-strikethrough/1.0.4: - resolution: {integrity: sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-classify-character: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-table/1.0.5: - resolution: {integrity: sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm-tagfilter/1.0.1: - resolution: {integrity: sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA==} - dependencies: - micromark-util-types: 1.0.2 - dev: false - - /micromark-extension-gfm-task-list-item/1.0.3: - resolution: {integrity: sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-extension-gfm/2.0.1: - resolution: {integrity: sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==} - dependencies: - micromark-extension-gfm-autolink-literal: 1.0.3 - micromark-extension-gfm-footnote: 1.0.4 - micromark-extension-gfm-strikethrough: 1.0.4 - micromark-extension-gfm-table: 1.0.5 - micromark-extension-gfm-tagfilter: 1.0.1 - micromark-extension-gfm-task-list-item: 1.0.3 - micromark-util-combine-extensions: 1.0.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-destination/1.0.0: - resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-label/1.0.2: - resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-factory-space/1.0.0: - resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-factory-title/1.0.2: - resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-factory-whitespace/1.0.0: - resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} - dependencies: - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-character/1.1.0: - resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} - dependencies: - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-chunked/1.0.0: - resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} - dependencies: - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-classify-character/1.0.0: - resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-combine-extensions/1.0.0: - resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-decode-numeric-character-reference/1.0.0: - resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} - dependencies: - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-decode-string/1.0.2: - resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==} - dependencies: - decode-named-character-reference: 1.0.2 - micromark-util-character: 1.1.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-encode/1.0.1: - resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==} - dev: false - - /micromark-util-html-tag-name/1.1.0: - resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==} - dev: false - - /micromark-util-normalize-identifier/1.0.0: - resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} - dependencies: - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-resolve-all/1.0.0: - resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} - dependencies: - micromark-util-types: 1.0.2 - dev: false - - /micromark-util-sanitize-uri/1.1.0: - resolution: {integrity: sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==} - dependencies: - micromark-util-character: 1.1.0 - micromark-util-encode: 1.0.1 - micromark-util-symbol: 1.0.1 - dev: false - - /micromark-util-subtokenize/1.0.2: - resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==} - dependencies: - micromark-util-chunked: 1.0.0 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - dev: false - - /micromark-util-symbol/1.0.1: - resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==} - dev: false - - /micromark-util-types/1.0.2: - resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==} - dev: false - - /micromark/3.1.0: - resolution: {integrity: sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==} - dependencies: - '@types/debug': 4.1.7 - debug: 4.3.4 - decode-named-character-reference: 1.0.2 - micromark-core-commonmark: 1.0.6 - micromark-factory-space: 1.0.0 - micromark-util-character: 1.1.0 - micromark-util-chunked: 1.0.0 - micromark-util-combine-extensions: 1.0.0 - micromark-util-decode-numeric-character-reference: 1.0.0 - micromark-util-encode: 1.0.1 - micromark-util-normalize-identifier: 1.0.0 - micromark-util-resolve-all: 1.0.0 - micromark-util-sanitize-uri: 1.1.0 - micromark-util-subtokenize: 1.0.2 - micromark-util-symbol: 1.0.1 - micromark-util-types: 1.0.2 - uvu: 0.5.6 - transitivePeerDependencies: - - supports-color - dev: false - - /micromatch/3.1.10: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /microseconds/0.2.0: - resolution: {integrity: sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==} - dev: false - - /mime-db/1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - /mime-types/2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - - /mime/1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /mime/2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - dev: true - - /mimic-fn/2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /min-indent/1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - dev: true - - /minimatch/3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - - /minimatch/5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist-options/4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - dev: true - - /minimist/1.2.7: - resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - dev: true - - /minipass/3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minipass/4.0.0: - resolution: {integrity: sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: true - - /minizlib/2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - dev: true - - /mitt/1.2.0: - resolution: {integrity: sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==} - dev: false - - /mixin-deep/1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} - dependencies: - for-in: 1.0.2 - is-extendable: 1.0.1 - dev: true - - /mkdirp/0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.7 - dev: true - - /mkdirp/1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /monaco-editor/0.34.1: - resolution: {integrity: sha512-FKc80TyiMaruhJKKPz5SpJPIjL+dflGvz4CpuThaPMc94AyN7SeC9HQ8hrvaxX7EyHdJcUY5i4D0gNyJj1vSZQ==} - dev: false - - /mri/1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - - /ms/2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - - /ms/2.1.1: - resolution: {integrity: sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==} - dev: true - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /ms/2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /nano-css/5.3.5_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==} - peerDependencies: - react: '*' - react-dom: '*' - dependencies: - css-tree: 1.1.3 - csstype: 3.1.1 - fastest-stable-stringify: 2.0.2 - inline-style-prefixer: 6.0.4 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - rtl-css-js: 1.16.1 - sourcemap-codec: 1.4.8 - stacktrace-js: 2.0.2 - stylis: 4.1.3 - dev: false - - /nano-time/1.0.0: - resolution: {integrity: sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==} - dependencies: - big-integer: 1.6.51 - dev: false - - /nanoclone/0.2.1: - resolution: {integrity: sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==} - dev: false - - /nanoid/3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - /nanomatch/1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - fragment-cache: 0.2.1 - is-windows: 1.0.2 - kind-of: 6.0.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /natural-compare-lite/1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true - - /natural-compare/1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /needle/3.2.0: - resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} - engines: {node: '>= 4.4.x'} - hasBin: true - requiresBuild: true - dependencies: - debug: 3.2.7 - iconv-lite: 0.6.3 - sax: 1.2.4 - transitivePeerDependencies: - - supports-color - dev: true - optional: true - - /negotiator/0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true - - /neo-async/2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /netmask/2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - dev: true - - /nimma/0.2.2: - resolution: {integrity: sha512-V52MLl7BU+tH2Np9tDrIXK8bql3MVUadnMIl/0/oZSGC9keuro0O9UUv9QKp0aMvtN8HRew4G7byY7H4eWsxaQ==} - engines: {node: ^12.20 || >=14.13} - dependencies: - '@jsep-plugin/regex': 1.0.3_jsep@1.3.8 - '@jsep-plugin/ternary': 1.1.3_jsep@1.3.8 - astring: 1.8.4 - jsep: 1.3.8 - optionalDependencies: - jsonpath-plus: 6.0.1 - lodash.topath: 4.5.2 - dev: true - - /node-dir/0.1.17: - resolution: {integrity: sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==} - engines: {node: '>= 0.10.5'} - dependencies: - minimatch: 3.1.2 - dev: true - - /node-fetch-h2/2.3.0: - resolution: {integrity: sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==} - engines: {node: 4.x || >=6.0.0} - dependencies: - http2-client: 1.3.5 - dev: true - - /node-fetch-native/1.0.1: - resolution: {integrity: sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==} - dev: true - - /node-fetch/2.6.7: - resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - - /node-fetch/2.6.8: - resolution: {integrity: sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-fetch/2.6.9: - resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-int64/0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true - - /node-readfiles/0.2.0: - resolution: {integrity: sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==} - dependencies: - es6-promise: 3.3.1 - dev: true - - /node-releases/2.0.8: - resolution: {integrity: sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==} - - /nopt/4.0.3: - resolution: {integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==} - hasBin: true - dependencies: - abbrev: 1.1.1 - osenv: 0.1.5 - dev: true - - /normalize-package-data/2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.1 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-package-data/3.0.3: - resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} - engines: {node: '>=10'} - dependencies: - hosted-git-info: 4.1.0 - is-core-module: 2.11.0 - semver: 7.3.8 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-path/3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - /npm-normalize-package-bin/1.0.1: - resolution: {integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==} - dev: true - - /npm-run-path/4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npmlog/5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - dev: true - - /nwsapi/2.2.2: - resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} - dev: true - - /oas-kit-common/1.0.8: - resolution: {integrity: sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==} - dependencies: - fast-safe-stringify: 2.1.1 - dev: true - - /oas-linter/3.2.2: - resolution: {integrity: sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==} - dependencies: - '@exodus/schemasafe': 1.0.0-rc.9 - should: 13.2.3 - yaml: 1.10.2 - dev: true - - /oas-resolver/2.5.6: - resolution: {integrity: sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==} - hasBin: true - dependencies: - node-fetch-h2: 2.3.0 - oas-kit-common: 1.0.8 - reftools: 1.1.9 - yaml: 1.10.2 - yargs: 17.6.2 - dev: true - - /oas-schema-walker/1.1.5: - resolution: {integrity: sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==} - dev: true - - /oas-validator/5.0.8: - resolution: {integrity: sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==} - dependencies: - call-me-maybe: 1.0.2 - oas-kit-common: 1.0.8 - oas-linter: 3.2.2 - oas-resolver: 2.5.6 - oas-schema-walker: 1.1.5 - reftools: 1.1.9 - should: 13.2.3 - yaml: 1.10.2 - dev: true - - /object-assign/4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-copy/0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} - dependencies: - copy-descriptor: 0.1.1 - define-property: 0.2.5 - kind-of: 3.2.2 - dev: true - - /object-inspect/1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: true - - /object-is/1.1.5: - resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - dev: true - - /object-keys/1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object-visit/1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /object.assign/4.1.4: - resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries/1.1.6: - resolution: {integrity: sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - dev: true - - /object.fromentries/2.0.6: - resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - dev: true - - /object.hasown/1.1.2: - resolution: {integrity: sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==} - dependencies: - define-properties: 1.1.4 - es-abstract: 1.21.1 - dev: true - - /object.pick/1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /object.values/1.1.6: - resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - dev: true - - /oblivious-set/1.0.0: - resolution: {integrity: sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==} - dev: false - - /on-finished/2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /on-headers/1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: true - - /once/1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /onetime/5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /ono/4.0.11: - resolution: {integrity: sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==} - dependencies: - format-util: 1.0.5 - dev: true - - /open/7.4.2: - resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - - /open/8.4.0: - resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: true - - /openapi3-ts/3.1.2: - resolution: {integrity: sha512-S8fijNOqe/ut0kEDAwHZnI7sVYqb8Q3XnISmSyXmK76jgrcf4ableI75KTY1qdksd9EI/t39Vi5M4VYKrkNKfQ==} - dependencies: - yaml: 2.2.1 - dev: true - - /optionator/0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - dev: true - - /optionator/0.9.1: - resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.3 - dev: true - - /orval/6.11.1_typescript@4.9.5: - resolution: {integrity: sha512-3QjI9i8mp/lT+ufJQWghQyCf6vNXqKVHva2IgLL/OWEuBA8AsGPXvJvCeqzFmi+fBSC7LzpR2Mkyle7dxfycLQ==} - hasBin: true - dependencies: - '@apidevtools/swagger-parser': 10.1.0 - '@orval/angular': 6.11.1 - '@orval/axios': 6.11.1 - '@orval/core': 6.11.1 - '@orval/msw': 6.11.1 - '@orval/query': 6.11.1 - '@orval/swr': 6.11.1 - ajv: 8.12.0 - cac: 6.7.14 - chalk: 4.1.2 - chokidar: 3.5.3 - enquirer: 2.3.6 - execa: 5.1.1 - find-up: 5.0.0 - fs-extra: 10.1.0 - lodash.uniq: 4.5.0 - openapi3-ts: 3.1.2 - string-argv: 0.3.1 - tsconfck: 2.0.2_typescript@4.9.5 - transitivePeerDependencies: - - encoding - - openapi-types - - supports-color - - typescript - dev: true - - /os-homedir/1.0.2: - resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} - engines: {node: '>=0.10.0'} - dev: true - - /os-tmpdir/1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /osenv/0.1.5: - resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} - dependencies: - os-homedir: 1.0.2 - os-tmpdir: 1.0.2 - dev: true - - /p-limit/2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit/3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate/3.0.0: - resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} - engines: {node: '>=6'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate/4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate/5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map/4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - dev: true - - /p-try/2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /pac-proxy-agent/5.0.0: - resolution: {integrity: sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==} - engines: {node: '>= 8'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - get-uri: 3.0.2 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - pac-resolver: 5.0.1 - raw-body: 2.5.1 - socks-proxy-agent: 5.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /pac-resolver/5.0.1: - resolution: {integrity: sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==} - engines: {node: '>= 8'} - dependencies: - degenerator: 3.0.2 - ip: 1.1.8 - netmask: 2.0.2 - dev: true - - /pad/2.3.0: - resolution: {integrity: sha512-lxrgnOG5AXmzMRT1O5urWtYFxHnFSE+QntgTHij1nvS4W+ubhQLmQRHmZXDeEvk9I00itAixLqU9Q6fE0gW3sw==} - engines: {node: '>= 4.0.0'} - dependencies: - wcwidth: 1.0.1 - dev: true - - /parent-module/1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - - /parse-entities/4.0.0: - resolution: {integrity: sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ==} - dependencies: - '@types/unist': 2.0.6 - character-entities: 2.0.2 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.0.2 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - dev: false - - /parse-json/5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.18.6 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - /parse-node-version/1.0.1: - resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} - engines: {node: '>= 0.10'} - dev: true - - /parse-srcset/1.0.2: - resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} - dev: false - - /parse5/7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - dependencies: - entities: 4.4.0 - dev: true - - /parseurl/1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: true - - /pascalcase/0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - dev: true - - /path-exists/3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - dev: true - - /path-exists/4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute/1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - /path-key/3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse/1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - /path-to-regexp/0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: true - - /path-type/4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - /pathe/1.1.0: - resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} - dev: true - - /pend/1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: true - - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - /pidtree/0.5.0: - resolution: {integrity: sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==} - engines: {node: '>=0.10'} - hasBin: true - dev: true - - /pify/4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - - /pirates/4.0.5: - resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir/3.0.0: - resolution: {integrity: sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==} - engines: {node: '>=6'} - dependencies: - find-up: 3.0.0 - dev: true - - /pkg-dir/4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pkg-dir/5.0.0: - resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} - engines: {node: '>=10'} - dependencies: - find-up: 5.0.0 - dev: true - - /polished/4.2.2: - resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==} - engines: {node: '>=10'} - dependencies: - '@babel/runtime': 7.20.7 - dev: true - - /pony-cause/1.1.1: - resolution: {integrity: sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g==} - engines: {node: '>=12.0.0'} - dev: true - - /popmotion/11.0.3: - resolution: {integrity: sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==} - dependencies: - framesync: 6.0.1 - hey-listen: 1.0.8 - style-value-types: 5.0.0 - tslib: 2.4.1 - dev: false - - /posix-character-classes/0.1.1: - resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} - engines: {node: '>=0.10.0'} - dev: true - - /postcss-filter-plugins/3.0.1: - resolution: {integrity: sha512-tRKbW4wWBEkSSFuJtamV2wkiV9rj6Yy7P3Y13+zaynlPEEZt8EgYKn3y/RBpMeIhNmHXFlSdzofml65hD5OafA==} - dependencies: - postcss: 8.4.21 - dev: true - - /postcss-icss-keyframes/0.2.1: - resolution: {integrity: sha512-4m+hLY5TVqoTM198KKnzdNudyu1OvtqwD+8kVZ9PNiEO4+IfHYoyVvEXsOHjV8nZ1k6xowf+nY4HlUfZhOFvvw==} - dependencies: - icss-utils: 3.0.1 - postcss: 8.4.21 - postcss-value-parser: 3.3.1 - dev: true - - /postcss-icss-selectors/2.0.3: - resolution: {integrity: sha512-dxFtq+wscbU9faJaH8kIi98vvCPDbt+qg1g9GoG0os1PY3UvgY1Y2G06iZrZb1iVC9cyFfafwSY1IS+IQpRQ4w==} - dependencies: - css-selector-tokenizer: 0.7.3 - generic-names: 1.0.3 - icss-utils: 3.0.1 - lodash: 4.17.21 - postcss: 8.4.21 - dev: true - - /postcss-load-config/3.1.4_aesdjsunmf4wiehhujt67my7tu: - resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} - engines: {node: '>= 10'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - dependencies: - lilconfig: 2.0.5 - postcss: 8.4.21 - ts-node: 10.9.1_cin3sed6ohfsopbmt6orxeb4o4 - yaml: 1.10.2 - dev: true - - /postcss-media-query-parser/0.2.3: - resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} - dev: true - - /postcss-resolve-nested-selector/0.1.1: - resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} - dev: true - - /postcss-safe-parser/6.0.0_postcss@8.4.21: - resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.3.3 - dependencies: - postcss: 8.4.21 - dev: true - - /postcss-scss/4.0.6: - resolution: {integrity: sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.4.19 - dev: true - - /postcss-selector-parser/6.0.11: - resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-value-parser/3.3.1: - resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==} - - /postcss-value-parser/4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - /postcss/8.4.21: - resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - - /prelude-ls/1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: true - - /prelude-ls/1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-linter-helpers/1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.2.0 - dev: true - - /prettier/2.8.3: - resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /pretty-format/27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - dev: true - - /pretty-format/29.3.1: - resolution: {integrity: sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.0.0 - ansi-styles: 5.2.0 - react-is: 18.2.0 - dev: true - - /pretty-hrtime/1.0.3: - resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} - engines: {node: '>= 0.8'} - dev: true - - /printable-characters/1.0.42: - resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} - dev: true - - /process-nextick-args/2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /process/0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: true - - /progress/2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: true - - /prompts/2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /prop-types-extra/1.1.1_react@17.0.2: - resolution: {integrity: sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==} - peerDependencies: - react: '>=0.14.0' - dependencies: - react: 17.0.2 - react-is: 16.13.1 - warning: 4.0.3 - dev: false - - /prop-types/15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - /property-expr/2.0.5: - resolution: {integrity: sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==} - dev: false - - /property-information/6.2.0: - resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} - dev: false - - /protobufjs/6.11.3: - resolution: {integrity: sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==} - hasBin: true - requiresBuild: true - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/long': 4.0.2 - '@types/node': 17.0.45 - long: 4.0.0 - dev: false - - /protobufjs/7.1.2: - resolution: {integrity: sha512-4ZPTPkXCdel3+L81yw3dG6+Kq3umdWKh7Dc7GW/CpNk4SX3hK58iPCWeCyhVTDrbkNeKrYNZ7EojM5WDaEWTLQ==} - engines: {node: '>=12.0.0'} - requiresBuild: true - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 17.0.45 - long: 5.2.1 - dev: false - - /proxy-addr/2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: true - - /proxy-agent/5.0.0: - resolution: {integrity: sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==} - engines: {node: '>= 8'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - lru-cache: 5.1.1 - pac-proxy-agent: 5.0.0 - proxy-from-env: 1.1.0 - socks-proxy-agent: 5.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /proxy-from-env/1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true - - /prr/1.0.1: - resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} - dev: true - optional: true - - /psl/1.9.0: - resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} - dev: true - - /punycode/1.3.2: - resolution: {integrity: sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==} - dev: false - - /punycode/2.2.0: - resolution: {integrity: sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==} - engines: {node: '>=6'} - dev: true - - /puppeteer-core/2.1.1: - resolution: {integrity: sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==} - engines: {node: '>=8.16.0'} - dependencies: - '@types/mime-types': 2.1.1 - debug: 4.3.4 - extract-zip: 1.7.0 - https-proxy-agent: 4.0.0 - mime: 2.6.0 - mime-types: 2.1.35 - progress: 2.0.3 - proxy-from-env: 1.1.0 - rimraf: 2.7.1 - ws: 6.2.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /qs/6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.4 - dev: true - - /query-string/6.14.1: - resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} - engines: {node: '>=6'} - dependencies: - decode-uri-component: 0.2.2 - filter-obj: 1.1.0 - split-on-first: 1.1.0 - strict-uri-encode: 2.0.0 - dev: false - - /querystring/0.2.0: - resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} - engines: {node: '>=0.4.x'} - deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. - dev: false - - /querystringify/2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - dev: true - - /queue-microtask/1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /quick-lru/4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true - - /ramda/0.28.0: - resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==} - dev: true - - /range-parser/1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: true - - /raw-body/2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - - /react-colorful/5.6.1_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: true - - /react-component-managers/3.2.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-SqtB09hS1ir0koBNybvNbNAB3k/r7IbIGbXSxvkkTV0m50s+4oJ59KYsbPAQ/2DhE169Rc5V26d674EcGcDbGA==} - peerDependencies: - react: '>=15.3.0' - react-dom: '>=15.3.0' - dependencies: - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - spy-on-component: 1.1.3 - dev: false - - /react-datepicker/4.8.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-u69zXGHMpxAa4LeYR83vucQoUCJQ6m/WBsSxmUMu/M8ahTSVMMyiyQzauHgZA2NUr9y0FUgOAix71hGYUb6tvg==} - peerDependencies: - react: ^16.9.0 || ^17 || ^18 - react-dom: ^16.9.0 || ^17 || ^18 - dependencies: - '@popperjs/core': 2.11.6 - classnames: 2.3.2 - date-fns: 2.29.3 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-onclickoutside: 6.12.2_sfoxds7t5ydpegc3knd667wn6m - react-popper: 2.3.0_vov5yimr6vvxyufd6uigwwkst4 - dev: false - - /react-docgen-typescript/2.2.2_typescript@4.9.5: - resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==} - peerDependencies: - typescript: '>= 4.3.x' - dependencies: - typescript: 4.9.5 - dev: true - - /react-docgen/6.0.0-alpha.3: - resolution: {integrity: sha512-DDLvB5EV9As1/zoUsct6Iz2Cupw9FObEGD3DMcIs3EDFIoSKyz8FZtoWj3Wj+oodrU4/NfidN0BL5yrapIcTSA==} - engines: {node: '>=12.0.0'} - hasBin: true - dependencies: - '@babel/core': 7.20.12 - '@babel/generator': 7.20.7 - ast-types: 0.14.2 - commander: 2.20.3 - doctrine: 3.0.0 - estree-to-babel: 3.2.1 - neo-async: 2.6.2 - node-dir: 0.1.17 - resolve: 1.22.1 - strip-indent: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /react-dom/17.0.2_react@17.0.2: - resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} - peerDependencies: - react: 17.0.2 - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react: 17.0.2 - scheduler: 0.20.2 - - /react-element-to-jsx-string/15.0.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==} - peerDependencies: - react: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 - react-dom: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 - dependencies: - '@base2/pretty-print-object': 1.0.1 - is-plain-object: 5.0.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-is: 18.1.0 - dev: true - - /react-error-boundary/3.1.4_react@17.0.2: - resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==} - engines: {node: '>=10', npm: '>=6'} - peerDependencies: - react: '>=16.13.1' - dependencies: - '@babel/runtime': 7.20.7 - react: 17.0.2 - dev: true - - /react-fast-compare/2.0.4: - resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} - dev: false - - /react-fast-compare/3.2.0: - resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==} - - /react-helmet-async/1.3.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==} - peerDependencies: - react: ^16.6.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@babel/runtime': 7.20.7 - invariant: 2.2.4 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-fast-compare: 3.2.0 - shallowequal: 1.1.0 - dev: false - - /react-inspector/6.0.1_react@17.0.2: - resolution: {integrity: sha512-cxKSeFTf7jpSSVddm66sKdolG90qURAX3g1roTeaN6x0YEbtWc8JpmFN9+yIqLNH2uEkYerWLtJZIXRIFuBKrg==} - peerDependencies: - react: ^16.8.4 || ^17.0.0 || ^18.0.0 - dependencies: - react: 17.0.2 - dev: true - - /react-intersection-observer/9.4.2_react@17.0.2: - resolution: {integrity: sha512-AdK+ryzZ7U9ZJYttDUZ8q2Am3nqE0exg5Ryl5Y124KeVsix/1hGZPbdu58EqA98TwnzwDNWHxg/kwNawmIiUig==} - peerDependencies: - react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 17.0.2 - dev: false - - /react-intl/6.2.5_oatgdhaahtizs2uezdzbohxvne: - resolution: {integrity: sha512-nz21POTKbE0sPEuEJU4o5YTZYY7VlIYCPNJaD6D2+xKyk6Noj6DoUK0LRO9LXuQNUuQ044IZl3m6ymzZRj8XFQ==} - peerDependencies: - react: ^16.6.0 || 17 || 18 - typescript: ^4.7 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@formatjs/ecma402-abstract': 1.14.3 - '@formatjs/icu-messageformat-parser': 2.1.14 - '@formatjs/intl': 2.6.3_typescript@4.9.5 - '@formatjs/intl-displaynames': 6.2.3 - '@formatjs/intl-listformat': 7.1.7 - '@types/hoist-non-react-statics': 3.3.1 - '@types/react': 17.0.52 - hoist-non-react-statics: 3.3.2 - intl-messageformat: 10.2.5 - react: 17.0.2 - tslib: 2.4.1 - typescript: 4.9.5 - dev: false - - /react-is/16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - /react-is/17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - - /react-is/18.1.0: - resolution: {integrity: sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==} - dev: true - - /react-is/18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - dev: true - - /react-lazylog/4.5.3_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-lyov32A/4BqihgXgtNXTHCajXSXkYHPlIEmV8RbYjHIMxCFSnmtdg4kDCI3vATz7dURtiFTvrw5yonHnrS+NNg==} - peerDependencies: - react: '>=16.3.0' - dependencies: - '@mattiasbuelens/web-streams-polyfill': 0.2.1 - fetch-readablestream: 0.2.0 - immutable: 3.8.2 - mitt: 1.2.0 - prop-types: 15.8.1 - react: 17.0.2 - react-string-replace: 0.4.4 - react-virtualized: 9.22.3_wem7zdhrj6jola7ic3qcehiqii_sfoxds7t5ydpegc3knd667wn6m - text-encoding-utf-8: 1.0.2 - whatwg-fetch: 2.0.4 - transitivePeerDependencies: - - react-dom - dev: false - - /react-lifecycles-compat/3.0.4: - resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} - dev: false - - /react-markdown/7.1.2_q5o373oqrklnndq2vhekyuzhxi: - resolution: {integrity: sha512-ibMcc0EbfmbwApqJD8AUr0yls8BSrKzIbHaUsPidQljxToCqFh34nwtu3CXNEItcVJNzpjDHrhK8A+MAh2JW3A==} - peerDependencies: - '@types/react': '>=16' - react: '>=16' - dependencies: - '@types/hast': 2.3.4 - '@types/react': 17.0.52 - '@types/unist': 2.0.6 - comma-separated-tokens: 2.0.3 - hast-util-whitespace: 2.0.1 - prop-types: 15.8.1 - property-information: 6.2.0 - react: 17.0.2 - react-is: 17.0.2 - remark-parse: 10.0.1 - remark-rehype: 9.1.0 - space-separated-tokens: 2.0.2 - style-to-object: 0.3.0 - unified: 10.1.2 - unist-util-visit: 4.1.1 - vfile: 5.3.6 - transitivePeerDependencies: - - supports-color - dev: false - - /react-measure/2.5.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-M+rpbTLWJ3FD6FXvYV6YEGvQ5tMayQ3fGrZhRPHrE9bVlBYfDCLuDcgNttYfk8IqfOI03jz6cbpqMRTUclQnaA==} - peerDependencies: - react: '>0.13.0' - react-dom: '>0.13.0' - dependencies: - '@babel/runtime': 7.20.7 - get-node-dimensions: 1.2.1 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - resize-observer-polyfill: 1.5.1 - dev: false - - /react-onclickoutside/6.12.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-NMXGa223OnsrGVp5dJHkuKxQ4czdLmXSp5jSV9OqiCky9LOpPATn3vLldc+q5fK3gKbEHvr7J1u0yhBh/xYkpA==} - peerDependencies: - react: ^15.5.x || ^16.x || ^17.x || ^18.x - react-dom: ^15.5.x || ^16.x || ^17.x || ^18.x - dependencies: - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react-paginate/8.1.4_react@17.0.2: - resolution: {integrity: sha512-c3rxjcTEqeDQa6LqXifxLeFguY2qy2CHGRphVjHLFFMGfIHyaJ+v3bOvIlLYEeohwQ1q+cQpknjsqBVrkc/SNA==} - peerDependencies: - react: ^16 || ^17 || ^18 - dependencies: - prop-types: 15.8.1 - react: 17.0.2 - dev: false - - /react-popper/2.3.0_vov5yimr6vvxyufd6uigwwkst4: - resolution: {integrity: sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==} - peerDependencies: - '@popperjs/core': ^2.0.0 - react: ^16.8.0 || ^17 || ^18 - react-dom: ^16.8.0 || ^17 || ^18 - dependencies: - '@popperjs/core': 2.11.6 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-fast-compare: 3.2.0 - warning: 4.0.3 - - /react-query/3.39.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-F6hYDKyNgDQfQOuR1Rsp3VRzJnWHx6aRnnIZHMNGGgbL3SBgpZTDg8MQwmxOgpCAoqZJA+JSNCydF1xGJqKOCA==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: '*' - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - dependencies: - '@babel/runtime': 7.20.7 - broadcast-channel: 3.7.0 - match-sorter: 6.3.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react-reflex/4.0.9_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-XFTNRekFK4ul8mzVd1lniKT/SI0FvNYhXyLNl5gagS1i3iW9QKlpFYcRfVhZlxxaYHb8UyLOs3+H4Ay5cjtbxQ==} - peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@babel/runtime': 7.20.7 - lodash.throttle: 4.1.1 - prop-types: 15.8.1 - react: 17.0.2 - react-measure: 2.5.2_sfoxds7t5ydpegc3knd667wn6m - transitivePeerDependencies: - - react-dom - dev: false - - /react-refresh/0.14.0: - resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} - engines: {node: '>=0.10.0'} - dev: true - - /react-resize-detector/7.1.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw==} - peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - lodash: 4.17.21 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react-resize-detector/8.0.3_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-c3eqm5BVcluVhxHsBQnhyPO/5uYB3XHIHz6D1ZOHzU2WcnZF0Cr3KLl5OIozRC2RSsdQlu5vn1PHEqrvKRnIYA==} - peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - lodash: 4.17.21 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react-router-dom/6.3.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - dependencies: - history: 5.3.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-router: 6.3.0_react@17.0.2 - dev: false - - /react-router/6.3.0_react@17.0.2: - resolution: {integrity: sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==} - peerDependencies: - react: '>=16.8' - dependencies: - history: 5.3.0 - react: 17.0.2 - dev: false - - /react-select-event/5.5.1: - resolution: {integrity: sha512-goAx28y0+iYrbqZA2FeRTreHHs/ZtSuKxtA+J5jpKT5RHPCbVZJ4MqACfPnWyFXsEec+3dP5bCrNTxIX8oYe9A==} - dependencies: - '@testing-library/dom': 8.20.0 - dev: true - - /react-select/5.7.0_dlps62spiehie4hvtd46aaye5u: - resolution: {integrity: sha512-lJGiMxCa3cqnUr2Jjtg9YHsaytiZqeNOKeibv6WF5zbK/fPegZ1hg3y/9P1RZVLhqBTs0PfqQLKuAACednYGhQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@babel/runtime': 7.20.7 - '@emotion/cache': 11.10.5 - '@emotion/react': 11.10.5_nehdyrcubdy45i2h35h56gfg7i - '@floating-ui/dom': 1.1.0 - '@types/react-transition-group': 4.4.5 - memoize-one: 6.0.0 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-transition-group: 4.4.5_sfoxds7t5ydpegc3knd667wn6m - use-isomorphic-layout-effect: 1.1.2_q5o373oqrklnndq2vhekyuzhxi - transitivePeerDependencies: - - '@babel/core' - - '@types/react' - dev: false - - /react-slick/0.29.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-TGdOKE+ZkJHHeC4aaoH85m8RnFyWqdqRfAGkhd6dirmATXMZWAxOpTLmw2Ll/jPTQ3eEG7ercFr/sbzdeYCJXA==} - peerDependencies: - react: ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - classnames: 2.3.2 - enquire.js: 2.1.6 - json2mq: 0.2.0 - lodash.debounce: 4.0.8 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - resize-observer-polyfill: 1.5.1 - dev: false - - /react-smooth/2.0.1_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-Own9TA0GPPf3as4vSwFhDouVfXP15ie/wIHklhyKBH5AN6NFtdk0UpHBnonV11BtqDkAWlt40MOUc+5srmW7NA==} - peerDependencies: - prop-types: ^15.6.0 - react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - fast-equals: 2.0.4 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-transition-group: 2.9.0_sfoxds7t5ydpegc3knd667wn6m - dev: false - - /react-string-replace/0.4.4: - resolution: {integrity: sha512-FAMkhxmDpCsGTwTZg7p/2v+/GTmxAp73so3fbSvlAcBBX36ujiGRNEaM/1u+jiYQrArhns+7eE92g2pi5E5FUA==} - engines: {node: '>=0.12.0'} - dependencies: - lodash: 4.17.21 - dev: false - - /react-table/7.8.0_react@17.0.2: - resolution: {integrity: sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==} - peerDependencies: - react: ^16.8.3 || ^17.0.0-0 || ^18.0.0 - dependencies: - react: 17.0.2 - dev: false - - /react-transition-group/2.9.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==} - peerDependencies: - react: '>=15.0.0' - react-dom: '>=15.0.0' - dependencies: - dom-helpers: 3.4.0 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-lifecycles-compat: 3.0.4 - dev: false - - /react-transition-group/4.4.5_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - dependencies: - '@babel/runtime': 7.20.7 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react-universal-interface/0.6.2_react@17.0.2+tslib@2.4.1: - resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} - peerDependencies: - react: '*' - tslib: '*' - dependencies: - react: 17.0.2 - tslib: 2.4.1 - dev: false - - /react-use-intercom/1.5.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-5bK3TtsZ9S18vWuagncc1tJA/+2WouIjMHtVlgcrvECYbDhOwFNMb1h1XDDcOIk4gZv+eDx/oiWLbNHFAR7lIA==} - engines: {node: '>=10'} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - dev: false - - /react-use/17.4.0_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - dependencies: - '@types/js-cookie': 2.2.7 - '@xobotyi/scrollbar-width': 1.9.5 - copy-to-clipboard: 3.3.3 - fast-deep-equal: 3.1.3 - fast-shallow-equal: 1.0.0 - js-cookie: 2.2.1 - nano-css: 5.3.5_sfoxds7t5ydpegc3knd667wn6m - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-universal-interface: 0.6.2_react@17.0.2+tslib@2.4.1 - resize-observer-polyfill: 1.5.1 - screenfull: 5.2.0 - set-harmonic-interval: 1.0.1 - throttle-debounce: 3.0.1 - ts-easing: 0.2.0 - tslib: 2.4.1 - dev: false - - /react-virtualized/9.22.3_wem7zdhrj6jola7ic3qcehiqii_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==} - peerDependencies: - react: ^15.3.0 || ^16.0.0-alpha - react-dom: ^15.3.0 || ^16.0.0-alpha - dependencies: - '@babel/runtime': 7.20.7 - clsx: 1.2.1 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-lifecycles-compat: 3.0.4 - dev: false - patched: true - - /react-widgets/4.6.1_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-x2n4EFQnk1ZG2rWsdekGK3js091k+b06e0CRI4pDEZ0uh/cft3NyGFKS5/x7CV/fN51kHMaM4r5IRGIbPfsLLw==} - peerDependencies: - react: '>=0.14.0' - react-dom: '>=0.14.0' - dependencies: - classnames: 2.3.2 - date-arithmetic: 3.1.0 - dom-helpers: 3.4.0 - invariant: 2.2.4 - prop-types-extra: 1.1.1_react@17.0.2 - react: 17.0.2 - react-component-managers: 3.2.2_sfoxds7t5ydpegc3knd667wn6m - react-dom: 17.0.2_react@17.0.2 - react-lifecycles-compat: 3.0.4 - react-transition-group: 2.9.0_sfoxds7t5ydpegc3knd667wn6m - uncontrollable: 7.2.1_react@17.0.2 - warning: 3.0.0 - dev: false - - /react/17.0.2: - resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - - /read-installed/4.0.3: - resolution: {integrity: sha512-O03wg/IYuV/VtnK2h/KXEt9VIbMUFbk3ERG0Iu4FhLZw0EP0T9znqrYDGn6ncbEsXUFaUjiVAWXHzxwt3lhRPQ==} - dependencies: - debuglog: 1.0.1 - read-package-json: 2.1.2 - readdir-scoped-modules: 1.1.0 - semver: 5.7.1 - slide: 1.1.6 - util-extend: 1.0.3 - optionalDependencies: - graceful-fs: 4.2.10 - dev: true - - /read-package-json/2.1.2: - resolution: {integrity: sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==} - dependencies: - glob: 7.2.3 - json-parse-even-better-errors: 2.3.1 - normalize-package-data: 2.5.0 - npm-normalize-package-bin: 1.0.1 - dev: true - - /read-pkg-up/7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg/5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - - /readable-stream/1.1.14: - resolution: {integrity: sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - dev: true - - /readable-stream/2.3.7: - resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream/3.6.0: - resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdir-scoped-modules/1.1.0: - resolution: {integrity: sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==} - deprecated: This functionality has been moved to @npmcli/fs - dependencies: - debuglog: 1.0.1 - dezalgo: 1.0.4 - graceful-fs: 4.2.10 - once: 1.4.0 - dev: true - - /readdirp/3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - - /recast/0.20.5: - resolution: {integrity: sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==} - engines: {node: '>= 4'} - dependencies: - ast-types: 0.14.2 - esprima: 4.0.1 - source-map: 0.6.1 - tslib: 2.5.0 - dev: true - - /recast/0.23.1: - resolution: {integrity: sha512-RokaBcoxSjXUDzz1TXSZmZsSW6ZpLmlA3GGqJ8uuTrQ9hZhEz+4Tpsc+gRvYRJ2BU4H+ZyUlg91eSGDw7bwy7g==} - engines: {node: '>= 4'} - dependencies: - assert: 2.0.0 - ast-types: 0.16.1 - esprima: 4.0.1 - source-map: 0.6.1 - tslib: 2.5.0 - dev: true - - /recharts-scale/0.4.5: - resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} - dependencies: - decimal.js-light: 2.5.1 - dev: false - - /recharts/2.3.2_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-2II30fGzKaypHfHNQNUhCfiLMxrOS/gF0WFahDIEFgXtJkVEe2DpZWFfEfAn+RU3B7/h2V/B05Bwmqq3rTXwLw==} - engines: {node: '>=12'} - peerDependencies: - prop-types: ^15.6.0 - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - classnames: 2.3.2 - eventemitter3: 4.0.7 - lodash: 4.17.21 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-is: 16.13.1 - react-resize-detector: 7.1.2_sfoxds7t5ydpegc3knd667wn6m - react-smooth: 2.0.1_sfoxds7t5ydpegc3knd667wn6m - recharts-scale: 0.4.5 - reduce-css-calc: 2.1.8 - victory-vendor: 36.6.8 - dev: false - - /rechoir/0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.1 - dev: true - - /redent/3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - dev: true - - /reduce-css-calc/2.1.8: - resolution: {integrity: sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==} - dependencies: - css-unit-converter: 1.1.2 - postcss-value-parser: 3.3.1 - dev: false - - /reftools/1.1.9: - resolution: {integrity: sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==} - dev: true - - /regenerate-unicode-properties/10.1.0: - resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} - engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - dev: true - - /regenerate/1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true - - /regenerator-runtime/0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - - /regenerator-transform/0.15.1: - resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} - dependencies: - '@babel/runtime': 7.20.7 - dev: true - - /regex-not/1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 3.0.2 - safe-regex: 1.1.0 - dev: true - - /regexp.prototype.flags/1.4.3: - resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - functions-have-names: 1.2.3 - dev: true - - /regexpp/3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - dev: true - - /regexpu-core/5.2.2: - resolution: {integrity: sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==} - engines: {node: '>=4'} - dependencies: - 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 - dev: true - - /regjsgen/0.7.1: - resolution: {integrity: sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==} - dev: true - - /regjsparser/0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /rehype-slug/5.1.0: - resolution: {integrity: sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==} - dependencies: - '@types/hast': 2.3.4 - github-slugger: 2.0.0 - hast-util-has-property: 2.0.1 - hast-util-heading-rank: 2.1.1 - hast-util-to-string: 2.0.0 - unified: 10.1.2 - unist-util-visit: 4.1.1 - dev: false - - /rehype-urls/1.1.1: - resolution: {integrity: sha512-ct9Kb/nAL6oe/O5fDc0xjiqm8Z9xgXdorOdDhZAWx7awucyiuYXU7Dax+23Gu24nnGwtdaCW6zslKAYzlEW1lw==} - dependencies: - hast-util-has-property: 1.0.4 - stdopt: 2.2.0 - unist-util-visit: 1.4.1 - dev: false - - /remark-directive/2.0.1: - resolution: {integrity: sha512-oosbsUAkU/qmUE78anLaJePnPis4ihsE7Agp0T/oqTzvTea8pOiaYEtfInU/+xMOVTS9PN5AhGOiaIVe4GD8gw==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-directive: 2.2.2 - micromark-extension-directive: 2.1.2 - unified: 10.1.2 - dev: false - - /remark-external-links/8.0.0: - resolution: {integrity: sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==} - dependencies: - extend: 3.0.2 - is-absolute-url: 3.0.3 - mdast-util-definitions: 4.0.0 - space-separated-tokens: 1.1.5 - unist-util-visit: 2.0.3 - dev: true - - /remark-frontmatter/4.0.1: - resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-frontmatter: 1.0.0 - micromark-extension-frontmatter: 1.0.0 - unified: 10.1.2 - dev: false - - /remark-gfm/3.0.1: - resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-gfm: 2.0.1 - micromark-extension-gfm: 2.0.1 - unified: 10.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-parse/10.0.1: - resolution: {integrity: sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==} - dependencies: - '@types/mdast': 3.0.10 - mdast-util-from-markdown: 1.2.0 - unified: 10.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /remark-rehype/9.1.0: - resolution: {integrity: sha512-oLa6YmgAYg19zb0ZrBACh40hpBLteYROaPLhBXzLgjqyHQrN+gVP9N/FJvfzuNNuzCutktkroXEZBrxAxKhh7Q==} - dependencies: - '@types/hast': 2.3.4 - '@types/mdast': 3.0.10 - mdast-util-to-hast: 11.3.0 - unified: 10.1.2 - dev: false - - /remark-slug/6.1.0: - resolution: {integrity: sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==} - dependencies: - github-slugger: 1.5.0 - mdast-util-to-string: 1.1.0 - unist-util-visit: 2.0.3 - dev: true - - /remove-accents/0.4.2: - resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==} - dev: false - - /repeat-element/1.1.4: - resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} - engines: {node: '>=0.10.0'} - dev: true - - /repeat-string/1.6.1: - resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} - engines: {node: '>=0.10'} - dev: true - - /require-all/3.0.0: - resolution: {integrity: sha512-jPGN876lc5exWYrMcgZSd7U42P0PmVQzxnQB13fCSzmyGnqQWW4WUz5DosZ/qe24hz+5o9lSvW2epBNZ1xa6Fw==} - engines: {node: '>= 0.8'} - dev: true - - /require-directory/2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - /require-from-string/2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /requires-port/1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: true - - /reserved-words/0.1.2: - resolution: {integrity: sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw==} - dev: true - - /reserved/0.1.2: - resolution: {integrity: sha512-/qO54MWj5L8WCBP9/UNe2iefJc+L9yETbH32xO/ft/EYPOTCR5k+azvDUgdCOKwZH8hXwPd0b8XBL78Nn2U69g==} - engines: {node: '>=0.8'} - dev: true - - /resize-observer-polyfill/1.5.1: - resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} - dev: false - - /resolve-cwd/3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - - /resolve-from/4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - /resolve-from/5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve-url/0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - dev: true - - /resolve.exports/1.1.1: - resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==} - engines: {node: '>=10'} - dev: true - - /resolve/1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true - dependencies: - is-core-module: 2.11.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /resolve/2.0.0-next.4: - resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} - hasBin: true - dependencies: - is-core-module: 2.11.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /restore-cursor/3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - - /ret/0.1.15: - resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} - engines: {node: '>=0.12'} - dev: true - - /reusify/1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rfdc/1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: true - - /rimraf/2.6.3: - resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rimraf/2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rimraf/3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - - /rollup/2.79.1: - resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} - engines: {node: '>=10.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /rollup/3.10.1: - resolution: {integrity: sha512-3Er+yel3bZbZX1g2kjVM+FW+RUWDxbG87fcqFM5/9HbPCTpbVp6JOLn7jlxnNlbu7s/N/uDA4EV/91E2gWnxzw==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /rtl-css-js/1.16.1: - resolution: {integrity: sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==} - dependencies: - '@babel/runtime': 7.20.7 - dev: false - - /run-parallel/1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /rxjs/7.8.0: - resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} - dependencies: - tslib: 2.4.1 - - /sade/1.8.1: - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} - engines: {node: '>=6'} - dependencies: - mri: 1.2.0 - dev: false - - /safe-buffer/5.1.1: - resolution: {integrity: sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==} - dev: true - - /safe-buffer/5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer/5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - /safe-regex-test/1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - is-regex: 1.1.4 - dev: true - - /safe-regex/1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} - dependencies: - ret: 0.1.15 - dev: true - - /safe-stable-stringify/1.1.1: - resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==} - dev: true - - /safer-buffer/2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /sanitize-html/2.8.1: - resolution: {integrity: sha512-qK5neD0SaMxGwVv5txOYv05huC3o6ZAA4h5+7nJJgWMNFUNRjcjLO6FpwAtKzfKCZ0jrG6xTk6eVFskbvOGblg==} - dependencies: - deepmerge: 4.2.2 - escape-string-regexp: 4.0.0 - htmlparser2: 8.0.1 - is-plain-object: 5.0.0 - parse-srcset: 1.0.2 - postcss: 8.4.21 - dev: false - - /sass/1.57.1: - resolution: {integrity: sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==} - engines: {node: '>=12.0.0'} - hasBin: true - dependencies: - chokidar: 3.5.3 - immutable: 4.2.2 - source-map-js: 1.0.2 - - /sax/1.2.4: - resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} - dev: true - - /saxes/6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} - dependencies: - xmlchars: 2.2.0 - dev: true - - /scheduler/0.20.2: - resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - - /screenfull/5.2.0: - resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} - engines: {node: '>=0.10.0'} - dev: false - - /semver/5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: true - - /semver/6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - - /semver/7.0.0: - resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} - hasBin: true - dev: true - - /semver/7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /send/0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /serve-favicon/2.5.0: - resolution: {integrity: sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==} - engines: {node: '>= 0.8.0'} - dependencies: - etag: 1.8.1 - fresh: 0.5.2 - ms: 2.1.1 - parseurl: 1.3.3 - safe-buffer: 5.1.1 - dev: true - - /serve-static/1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - - /set-blocking/2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true - - /set-harmonic-interval/1.0.1: - resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} - engines: {node: '>=6.9'} - dev: false - - /set-value/2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-extendable: 0.1.1 - is-plain-object: 2.0.4 - split-string: 3.1.0 - dev: true - - /setprototypeof/1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /shallow-clone/3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - dev: true - - /shallowequal/1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - dev: false - - /shebang-command/2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex/3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shelljs/0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - dev: true - - /should-equal/2.0.0: - resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==} - dependencies: - should-type: 1.4.0 - dev: true - - /should-format/3.0.3: - resolution: {integrity: sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==} - dependencies: - should-type: 1.4.0 - should-type-adaptors: 1.1.0 - dev: true - - /should-type-adaptors/1.1.0: - resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==} - dependencies: - should-type: 1.4.0 - should-util: 1.0.1 - dev: true - - /should-type/1.4.0: - resolution: {integrity: sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==} - dev: true - - /should-util/1.0.1: - resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==} - dev: true - - /should/13.2.3: - resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==} - dependencies: - should-equal: 2.0.0 - should-format: 3.0.3 - should-type: 1.4.0 - should-type-adaptors: 1.1.0 - should-util: 1.0.1 - dev: true - - /side-channel/1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.3 - object-inspect: 1.12.3 - dev: true - - /signal-exit/3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /simple-eval/1.0.0: - resolution: {integrity: sha512-kpKJR+bqTscgC0xuAl2xHN6bB12lHjC2DCUfqjAx19bQyO3R2EVLOurm3H9AUltv/uFVcSCVNc6faegR+8NYLw==} - engines: {node: '>=12'} - dependencies: - jsep: 1.3.8 - dev: true - - /simple-update-notifier/1.1.0: - resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==} - engines: {node: '>=8.10.0'} - dependencies: - semver: 7.0.0 - dev: true - - /sisteransi/1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash/3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slice-ansi/3.0.0: - resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - - /slice-ansi/4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - - /slice-ansi/5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 - dev: true - - /slide/1.1.6: - resolution: {integrity: sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==} - dev: true - - /smart-buffer/4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /snapdragon-node/2.1.1: - resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 1.0.0 - isobject: 3.0.1 - snapdragon-util: 3.0.1 - dev: true - - /snapdragon-util/3.0.1: - resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /snapdragon/0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - dependencies: - base: 0.11.2 - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /socks-proxy-agent/5.0.1: - resolution: {integrity: sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - socks: 2.7.1 - transitivePeerDependencies: - - supports-color - dev: true - - /socks/2.7.1: - resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} - engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} - dependencies: - ip: 2.0.0 - smart-buffer: 4.2.0 - dev: true - - /source-map-js/1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} - engines: {node: '>=0.10.0'} - - /source-map-resolve/0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.2 - resolve-url: 0.2.1 - source-map-url: 0.4.1 - urix: 0.1.0 - dev: true - - /source-map-support/0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map-support/0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map-url/0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - dev: true - - /source-map/0.5.6: - resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} - engines: {node: '>=0.10.0'} - dev: false - - /source-map/0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - - /source-map/0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - /source-map/0.7.4: - resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} - engines: {node: '>= 8'} - dev: true - - /sourcemap-codec/1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - deprecated: Please use @jridgewell/sourcemap-codec instead - - /space-separated-tokens/1.1.5: - resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} - dev: true - - /space-separated-tokens/2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - dev: false - - /spdx-compare/1.0.0: - resolution: {integrity: sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==} - dependencies: - array-find-index: 1.0.2 - spdx-expression-parse: 3.0.1 - spdx-ranges: 2.1.1 - dev: true - - /spdx-correct/3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.12 - dev: true - - /spdx-exceptions/2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse/3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.12 - dev: true - - /spdx-license-ids/3.0.12: - resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} - dev: true - - /spdx-ranges/2.1.1: - resolution: {integrity: sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==} - dev: true - - /spdx-satisfies/4.0.1: - resolution: {integrity: sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA==} - dependencies: - spdx-compare: 1.0.0 - spdx-expression-parse: 3.0.1 - spdx-ranges: 2.1.1 - dev: true - - /split-on-first/1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - dev: false - - /split-string/3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 3.0.2 - dev: true - - /sprintf-js/1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /spy-on-component/1.1.3: - resolution: {integrity: sha512-a7jgnoBSdkcDWIQQwtEgUq4etajwG6+wGIjfC9ARUKwKOdHxJd+utgHTgLn81ETizpsw4xddUS3W8VePedtaIQ==} - dev: false - - /stack-generator/2.0.10: - resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} - dependencies: - stackframe: 1.3.4 - dev: false - - /stack-utils/2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - dev: true - - /stackframe/1.3.4: - resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} - dev: false - - /stacktrace-gps/3.1.2: - resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} - dependencies: - source-map: 0.5.6 - stackframe: 1.3.4 - dev: false - - /stacktrace-js/2.0.2: - resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} - dependencies: - error-stack-parser: 2.1.4 - stack-generator: 2.0.10 - stacktrace-gps: 3.1.2 - dev: false - - /stacktracey/2.1.8: - resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} - dependencies: - as-table: 1.0.55 - get-source: 2.0.12 - dev: true - - /state-local/1.0.7: - resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} - dev: false - - /static-extend/0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 0.2.5 - object-copy: 0.1.0 - dev: true - - /statuses/2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /stdopt/2.2.0: - resolution: {integrity: sha512-D/p41NgXOkcj1SeGhfXOwv9z1K6EV3sjAUY5aeepVbgEHv7DpKWLTjhjScyzMWAQCAgUQys1mjH0eArm4cjRGw==} - dependencies: - is-arrayish: 0.3.2 - dev: false - - /stop-iteration-iterator/1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} - dependencies: - internal-slot: 1.0.4 - dev: true - - /store2/2.14.2: - resolution: {integrity: sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==} - dev: true - - /storybook/7.0.0-beta.38: - resolution: {integrity: sha512-9sGO7yrgD+XqoXSysWcUppRmp+umntsJqz9FAITDgnbtehX7rsSkvqxRfghtukIqzWow5zsv/YQLFGy/zv1oTg==} - hasBin: true - dependencies: - '@storybook/cli': 7.0.0-beta.38 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true - - /strict-uri-encode/2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - dev: false - - /string-argv/0.3.1: - resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} - engines: {node: '>=0.6.19'} - dev: true - - /string-convert/0.2.1: - resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} - dev: false - - /string-length/4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - dev: true - - /string-natural-compare/3.0.1: - resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} - dev: true - - /string-width/4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string-width/5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.0.1 - dev: true - - /string.prototype.matchall/4.0.8: - resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - get-intrinsic: 1.1.3 - has-symbols: 1.0.3 - internal-slot: 1.0.4 - regexp.prototype.flags: 1.4.3 - side-channel: 1.0.4 - dev: true - - /string.prototype.trimend/1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - dev: true - - /string.prototype.trimstart/1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.21.1 - dev: true - - /string_decoder/0.10.31: - resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} - dev: true - - /string_decoder/1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder/1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /stringify-entities/4.0.3: - resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - dev: false - - /strip-ansi/6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-ansi/7.0.1: - resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-bom/3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-bom/4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - dev: true - - /strip-final-newline/2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-indent/3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - dependencies: - min-indent: 1.0.1 - dev: true - - /strip-json-comments/3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /style-search/0.1.0: - resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} - dev: true - - /style-to-object/0.3.0: - resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} - dependencies: - inline-style-parser: 0.1.1 - dev: false - - /style-value-types/5.0.0: - resolution: {integrity: sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==} - dependencies: - hey-listen: 1.0.8 - tslib: 2.4.1 - dev: false - - /styled-components/5.3.6_sfoxds7t5ydpegc3knd667wn6m: - resolution: {integrity: sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==} - engines: {node: '>=10'} - requiresBuild: true - peerDependencies: - react: '>= 16.8.0' - react-dom: '>= 16.8.0' - react-is: '>= 16.8.0' - dependencies: - '@babel/helper-module-imports': 7.18.6 - '@babel/traverse': 7.20.12_supports-color@5.5.0 - '@emotion/is-prop-valid': 1.2.0 - '@emotion/stylis': 0.8.5 - '@emotion/unitless': 0.7.5 - babel-plugin-styled-components: 2.0.7_styled-components@5.3.6 - css-to-react-native: 3.1.0 - hoist-non-react-statics: 3.3.2 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - shallowequal: 1.1.0 - supports-color: 5.5.0 - dev: false - - /stylelint-config-css-modules/4.1.0_stylelint@14.16.1: - resolution: {integrity: sha512-w6d552NscwvpUEaUcmq8GgWXKRv6lVHLbDj6QIHSM2vCWr83qRqRvXBJCfXDyaG/J3Zojw2inU9VvU99ZlXuUw==} - peerDependencies: - stylelint: ^14.5.1 - dependencies: - stylelint: 14.16.1 - optionalDependencies: - stylelint-scss: 4.3.0_stylelint@14.16.1 - dev: true - - /stylelint-config-prettier-scss/0.0.1_stylelint@14.16.1: - resolution: {integrity: sha512-lBAYG9xYOh2LeWEPC/64xeUxwOTnQ8nDyBijQoWoJb10/bMGrUwnokpt8jegGck2Vbtxh6XGwH63z5qBcVHreQ==} - engines: {node: '>= 12'} - hasBin: true - peerDependencies: - stylelint: '>=11.0.0' - dependencies: - stylelint: 14.16.1 - stylelint-config-prettier: 9.0.4_stylelint@14.16.1 - dev: true - - /stylelint-config-prettier/9.0.4_stylelint@14.16.1: - resolution: {integrity: sha512-38nIGTGpFOiK5LjJ8Ma1yUgpKENxoKSOhbDNSemY7Ep0VsJoXIW9Iq/2hSt699oB9tReynfWicTAoIHiq8Rvbg==} - engines: {node: '>= 12'} - hasBin: true - peerDependencies: - stylelint: '>=11.0.0' - dependencies: - stylelint: 14.16.1 - dev: true - - /stylelint-config-recommended-scss/7.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-rGz1J4rMAyJkvoJW4hZasuQBB7y9KIrShb20l9DVEKKZSEi1HAy0vuNlR8HyCKy/jveb/BdaQFcoiYnmx4HoiA==} - peerDependencies: - stylelint: ^14.4.0 - dependencies: - postcss-scss: 4.0.6 - stylelint: 14.16.1 - stylelint-config-recommended: 8.0.0_stylelint@14.16.1 - stylelint-scss: 4.3.0_stylelint@14.16.1 - transitivePeerDependencies: - - postcss - dev: true - - /stylelint-config-recommended/8.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-IK6dWvE000+xBv9jbnHOnBq01gt6HGVB2ZTsot+QsMpe82doDQ9hvplxfv4YnpEuUwVGGd9y6nbaAnhrjcxhZQ==} - peerDependencies: - stylelint: ^14.8.0 - dependencies: - stylelint: 14.16.1 - dev: true - - /stylelint-config-standard-scss/5.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-zoXLibojHZYPFjtkc4STZtAJ2yGTq3Bb4MYO0oiyO6f/vNxDKRcSDZYoqN260Gv2eD5niQIr1/kr5SXlFj9kcQ==} - peerDependencies: - stylelint: ^14.9.0 - dependencies: - stylelint: 14.16.1 - stylelint-config-recommended-scss: 7.0.0_stylelint@14.16.1 - stylelint-config-standard: 26.0.0_stylelint@14.16.1 - transitivePeerDependencies: - - postcss - dev: true - - /stylelint-config-standard/26.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-hUuB7LaaqM8abvkOO84wh5oYSkpXgTzHu2Zza6e7mY+aOmpNTjoFBRxSLlzY0uAOMWEFx0OMKzr+reG1BUtcqQ==} - peerDependencies: - stylelint: ^14.9.0 - dependencies: - stylelint: 14.16.1 - stylelint-config-recommended: 8.0.0_stylelint@14.16.1 - dev: true - - /stylelint-scss/4.3.0_stylelint@14.16.1: - resolution: {integrity: sha512-GvSaKCA3tipzZHoz+nNO7S02ZqOsdBzMiCx9poSmLlb3tdJlGddEX/8QzCOD8O7GQan9bjsvLMsO5xiw6IhhIQ==} - peerDependencies: - stylelint: ^14.5.1 - dependencies: - lodash: 4.17.21 - postcss-media-query-parser: 0.2.3 - postcss-resolve-nested-selector: 0.1.1 - postcss-selector-parser: 6.0.11 - postcss-value-parser: 4.2.0 - stylelint: 14.16.1 - dev: true - - /stylelint/14.16.1: - resolution: {integrity: sha512-ErlzR/T3hhbV+a925/gbfc3f3Fep9/bnspMiJPorfGEmcBbXdS+oo6LrVtoUZ/w9fqD6o6k7PtUlCOsCRdjX/A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dependencies: - '@csstools/selector-specificity': 2.0.2_wajs5nedgkikc5pcuwett7legi - balanced-match: 2.0.0 - colord: 2.9.3 - cosmiconfig: 7.1.0 - css-functions-list: 3.1.0 - debug: 4.3.4 - fast-glob: 3.2.12 - fastest-levenshtein: 1.0.16 - file-entry-cache: 6.0.1 - global-modules: 2.0.0 - globby: 11.1.0 - globjoin: 0.1.4 - html-tags: 3.2.0 - ignore: 5.2.4 - import-lazy: 4.0.0 - imurmurhash: 0.1.4 - is-plain-object: 5.0.0 - known-css-properties: 0.26.0 - mathml-tag-names: 2.1.3 - meow: 9.0.0 - micromatch: 4.0.5 - normalize-path: 3.0.0 - picocolors: 1.0.0 - postcss: 8.4.21 - postcss-media-query-parser: 0.2.3 - postcss-resolve-nested-selector: 0.1.1 - postcss-safe-parser: 6.0.0_postcss@8.4.21 - postcss-selector-parser: 6.0.11 - postcss-value-parser: 4.2.0 - resolve-from: 5.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - style-search: 0.1.0 - supports-hyperlinks: 2.3.0 - svg-tags: 1.0.0 - table: 6.8.1 - v8-compile-cache: 2.3.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /stylis/4.1.3: - resolution: {integrity: sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==} - dev: false - - /stylus/0.59.0: - resolution: {integrity: sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==} - hasBin: true - dependencies: - '@adobe/css-tools': 4.0.2 - debug: 4.3.4 - glob: 7.2.3 - sax: 1.2.4 - source-map: 0.7.4 - transitivePeerDependencies: - - supports-color - dev: true - - /supports-color/5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - - /supports-color/7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color/8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color/9.3.1: - resolution: {integrity: sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==} - engines: {node: '>=12'} - dev: true - - /supports-hyperlinks/2.3.0: - resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - dev: true - - /supports-preserve-symlinks-flag/1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - /svg-parser/2.0.4: - resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} - dev: true - - /svg-tags/1.0.0: - resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} - dev: true - - /swagger2openapi/7.0.8: - resolution: {integrity: sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==} - hasBin: true - dependencies: - call-me-maybe: 1.0.2 - node-fetch: 2.6.9 - node-fetch-h2: 2.3.0 - node-readfiles: 0.2.0 - oas-kit-common: 1.0.8 - oas-resolver: 2.5.6 - oas-schema-walker: 1.1.5 - oas-validator: 5.0.8 - reftools: 1.1.9 - yaml: 1.10.2 - yargs: 17.6.2 - transitivePeerDependencies: - - encoding - dev: true - - /symbol-tree/3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - dev: true - - /synchronous-promise/2.0.16: - resolution: {integrity: sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==} - dev: true - - /table/6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.12.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /tar/6.1.13: - resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 4.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - dev: true - - /telejson/7.0.4: - resolution: {integrity: sha512-J4QEuCnYGXAI9KSN7RXK0a0cOW2ONpjc4IQbInGZ6c3stvplLAYyZjTnScrRd8deXVjNCFV1wXcLC7SObDuQYA==} - dependencies: - memoizerific: 1.11.3 - dev: true - - /temp-dir/2.0.0: - resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} - engines: {node: '>=8'} - dev: true - - /temp/0.8.4: - resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} - engines: {node: '>=6.0.0'} - dependencies: - rimraf: 2.6.3 - dev: true - - /tempy/1.0.1: - resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} - engines: {node: '>=10'} - dependencies: - del: 6.1.1 - is-stream: 2.0.1 - temp-dir: 2.0.0 - type-fest: 0.16.0 - unique-string: 2.0.0 - dev: true - - /test-exclude/6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - - /text-encoding-utf-8/1.0.2: - resolution: {integrity: sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==} - dev: false - - /text-table/0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /throttle-debounce/3.0.1: - resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} - engines: {node: '>=10'} - dev: false - - /through/2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - - /timezone-mock/1.3.6: - resolution: {integrity: sha512-YcloWmZfLD9Li5m2VcobkCDNVaLMx8ohAb/97l/wYS3m+0TIEK5PFNMZZfRcusc6sFjIfxu8qcJT0CNnOdpqmg==} - dev: true - - /tiny-invariant/1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} - dev: true - - /tiny-warning/1.0.3: - resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} - dev: false - - /tmpl/1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true - - /to-fast-properties/2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-object-path/0.3.0: - resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: true - - /to-regex-range/2.1.1: - resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - dev: true - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - - /to-regex/3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 2.0.2 - extend-shallow: 3.0.2 - regex-not: 1.0.2 - safe-regex: 1.1.0 - dev: true - - /toggle-selection/1.0.6: - resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} - dev: false - - /toidentifier/1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /toposort/2.0.2: - resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} - dev: false - - /tough-cookie/4.1.2: - resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} - engines: {node: '>=6'} - dependencies: - psl: 1.9.0 - punycode: 2.2.0 - universalify: 0.2.0 - url-parse: 1.5.10 - dev: true - - /tr46/0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - /tr46/3.0.0: - resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} - engines: {node: '>=12'} - dependencies: - punycode: 2.2.0 - dev: true - - /treeify/1.1.0: - resolution: {integrity: sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==} - engines: {node: '>=0.6'} - dev: true - - /trim-newlines/3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true - - /trough/2.1.0: - resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - dev: false - - /ts-dedent/2.2.0: - resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} - engines: {node: '>=6.10'} - dev: true - - /ts-easing/0.2.0: - resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} - dev: false - - /ts-node/10.9.1_cin3sed6ohfsopbmt6orxeb4o4: - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 17.0.45 - acorn: 8.8.1 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /tsconfck/2.0.2_typescript@4.9.5: - resolution: {integrity: sha512-H3DWlwKpow+GpVLm/2cpmok72pwRr1YFROV3YzAmvzfGFiC1zEM/mc9b7+1XnrxuXtEbhJ7xUSIqjPFbedp7aQ==} - engines: {node: ^14.13.1 || ^16 || >=18, pnpm: ^7.18.0} - hasBin: true - peerDependencies: - typescript: ^4.3.5 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - typescript: 4.9.5 - dev: true - - /tsconfig-paths/3.14.1: - resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.7 - strip-bom: 3.0.0 - dev: true - - /tsconfig-paths/4.1.2: - resolution: {integrity: sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==} - engines: {node: '>=6'} - dependencies: - json5: 2.2.3 - minimist: 1.2.7 - strip-bom: 3.0.0 - dev: true - - /tslib/1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - - /tslib/2.4.1: - resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} - - /tslib/2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - - /tsutils/3.21.0_typescript@4.9.5: - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 4.9.5 - dev: true - - /type-check/0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - dev: true - - /type-check/0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-detect/4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true - - /type-fest/0.16.0: - resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} - engines: {node: '>=10'} - dev: true - - /type-fest/0.18.1: - resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} - engines: {node: '>=10'} - dev: true - - /type-fest/0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest/0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest/0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest/0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - - /type-fest/2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - dev: true - - /type-is/1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: true - - /typed-array-length/1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} - dependencies: - call-bind: 1.0.2 - for-each: 0.3.3 - is-typed-array: 1.1.10 - dev: true - - /typedarray/0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - dev: true - - /typesafe-actions/5.1.0: - resolution: {integrity: sha512-bna6Yi1pRznoo6Bz1cE6btB/Yy8Xywytyfrzu/wc+NFW3ZF0I+2iCGImhBsoYYCOWuICtRO4yHcnDlzgo1AdNg==} - engines: {node: '>= 4'} - dev: false - - /typescript-plugin-css-modules/4.1.1_6qtx7vkbdhwvdm4crzlegk4mvi: - resolution: {integrity: sha512-kpVxGkY/go9eV5TP1YUDJ6SqwBx2OIuVStMCxKyg9PhJVFXjLYR7AuItVLwoz0NCdiemH91WhtgAjb96jI34DA==} - peerDependencies: - typescript: '>=3.9.0' - dependencies: - dotenv: 16.0.3 - icss-utils: 5.1.0_postcss@8.4.21 - less: 4.1.3 - lodash.camelcase: 4.3.0 - postcss: 8.4.21 - postcss-filter-plugins: 3.0.1 - postcss-icss-keyframes: 0.2.1 - postcss-icss-selectors: 2.0.3 - postcss-load-config: 3.1.4_aesdjsunmf4wiehhujt67my7tu - reserved-words: 0.1.2 - sass: 1.57.1 - source-map-js: 1.0.2 - stylus: 0.59.0 - tsconfig-paths: 4.1.2 - typescript: 4.9.5 - transitivePeerDependencies: - - supports-color - - ts-node - dev: true - - /typescript/4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} - hasBin: true - - /uglify-js/3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /unbox-primitive/1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /uncontrollable/7.2.1_react@17.0.2: - resolution: {integrity: sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==} - peerDependencies: - react: '>=15.0.0' - dependencies: - '@babel/runtime': 7.20.7 - '@types/react': 17.0.52 - invariant: 2.2.4 - react: 17.0.2 - react-lifecycles-compat: 3.0.4 - dev: false - - /unfetch/4.2.0: - resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} - dev: true - - /unicode-canonical-property-names-ecmascript/2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} - engines: {node: '>=4'} - dev: true - - /unicode-match-property-ecmascript/2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - dev: true - - /unicode-match-property-value-ecmascript/2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} - engines: {node: '>=4'} - dev: true - - /unicode-property-aliases-ecmascript/2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - dev: true - - /unified/10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} - dependencies: - '@types/unist': 2.0.6 - bail: 2.0.2 - extend: 3.0.2 - is-buffer: 2.0.5 - is-plain-obj: 4.1.0 - trough: 2.1.0 - vfile: 5.3.6 - dev: false - - /union-value/1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-union: 3.1.0 - get-value: 2.0.6 - is-extendable: 0.1.1 - set-value: 2.0.1 - dev: true - - /unique-string/2.0.0: - resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} - engines: {node: '>=8'} - dependencies: - crypto-random-string: 2.0.0 - dev: true - - /unist-builder/3.0.0: - resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-generated/2.0.0: - resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==} - dev: false - - /unist-util-is/3.0.0: - resolution: {integrity: sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==} - dev: false - - /unist-util-is/4.1.0: - resolution: {integrity: sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==} - dev: true - - /unist-util-is/5.1.1: - resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==} - dev: false - - /unist-util-position/4.0.3: - resolution: {integrity: sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-stringify-position/3.0.2: - resolution: {integrity: sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==} - dependencies: - '@types/unist': 2.0.6 - dev: false - - /unist-util-visit-parents/2.1.2: - resolution: {integrity: sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==} - dependencies: - unist-util-is: 3.0.0 - dev: false - - /unist-util-visit-parents/3.1.1: - resolution: {integrity: sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 4.1.0 - dev: true - - /unist-util-visit-parents/5.1.1: - resolution: {integrity: sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - dev: false - - /unist-util-visit/1.4.1: - resolution: {integrity: sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==} - dependencies: - unist-util-visit-parents: 2.1.2 - dev: false - - /unist-util-visit/2.0.3: - resolution: {integrity: sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 4.1.0 - unist-util-visit-parents: 3.1.1 - dev: true - - /unist-util-visit/4.1.1: - resolution: {integrity: sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==} - dependencies: - '@types/unist': 2.0.6 - unist-util-is: 5.1.1 - unist-util-visit-parents: 5.1.1 - dev: false - - /universalify/0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify/0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify/2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} - engines: {node: '>= 10.0.0'} - dev: true - - /unload/2.2.0: - resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==} - dependencies: - '@babel/runtime': 7.20.7 - detect-node: 2.1.0 - dev: false - - /unpipe/1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true - - /unplugin/0.10.2: - resolution: {integrity: sha512-6rk7GUa4ICYjae5PrAllvcDeuT8pA9+j5J5EkxbMFaV+SalHhxZ7X2dohMzu6C3XzsMT+6jwR/+pwPNR3uK9MA==} - dependencies: - acorn: 8.8.2 - chokidar: 3.5.3 - webpack-sources: 3.2.3 - webpack-virtual-modules: 0.4.6 - dev: true - - /unset-value/1.0.0: - resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} - engines: {node: '>=0.10.0'} - dependencies: - has-value: 0.3.1 - isobject: 3.0.1 - dev: true - - /untildify/4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true - - /update-browserslist-db/1.0.10_browserslist@4.21.4: - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.4 - escalade: 3.1.1 - picocolors: 1.0.0 - - /uri-js/4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.2.0 - dev: true - - /urijs/1.19.11: - resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} - dev: true - - /urix/0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} - deprecated: Please see https://github.com/lydell/urix#deprecated - dev: true - - /url-parse/1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - dev: true - - /url/0.11.0: - resolution: {integrity: sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==} - dependencies: - punycode: 1.3.2 - querystring: 0.2.0 - dev: false - - /use-isomorphic-layout-effect/1.1.2_q5o373oqrklnndq2vhekyuzhxi: - resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 17.0.52 - react: 17.0.2 - dev: false - - /use/3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - dev: true - - /util-deprecate/1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /util-extend/1.0.3: - resolution: {integrity: sha512-mLs5zAK+ctllYBj+iAQvlDCwoxU/WDOUaJkcFudeiAX6OajC6BKXJUa9a+tbtkC11dz2Ufb7h0lyvIOVn4LADA==} - dev: true - - /util/0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - dependencies: - inherits: 2.0.4 - is-arguments: 1.1.1 - is-generator-function: 1.0.10 - is-typed-array: 1.1.10 - which-typed-array: 1.1.9 - dev: true - - /utility-types/3.10.0: - resolution: {integrity: sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==} - engines: {node: '>= 4'} - dev: true - - /utils-merge/1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: true - - /uuid-browser/3.1.0: - resolution: {integrity: sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==} - dev: true - - /uuid/8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false - - /uuid/9.0.0: - resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} - hasBin: true - dev: false - - /uvu/0.5.6: - resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - dequal: 2.0.3 - diff: 5.1.0 - kleur: 4.1.5 - sade: 1.8.1 - dev: false - - /v8-compile-cache-lib/3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /v8-compile-cache/2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} - dev: true - - /v8-to-istanbul/9.0.1: - resolution: {integrity: sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==} - engines: {node: '>=10.12.0'} - dependencies: - '@jridgewell/trace-mapping': 0.3.17 - '@types/istanbul-lib-coverage': 2.0.4 - convert-source-map: 1.9.0 - dev: true - - /validate-npm-package-license/3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.1.1 - spdx-expression-parse: 3.0.1 - dev: true - - /validate-npm-package-name/3.0.0: - resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} - dependencies: - builtins: 1.0.3 - dev: true - - /validator/13.7.0: - resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==} - engines: {node: '>= 0.10'} - dev: true - - /vary/1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: true - - /vfile-message/3.1.3: - resolution: {integrity: sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA==} - dependencies: - '@types/unist': 2.0.6 - unist-util-stringify-position: 3.0.2 - dev: false - - /vfile/5.3.6: - resolution: {integrity: sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA==} - dependencies: - '@types/unist': 2.0.6 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.2 - vfile-message: 3.1.3 - dev: false - - /victory-vendor/36.6.8: - resolution: {integrity: sha512-H3kyQ+2zgjMPvbPqAl7Vwm2FD5dU7/4bCTQakFQnpIsfDljeOMDojRsrmJfwh4oAlNnWhpAf+mbAoLh8u7dwyQ==} - dependencies: - '@types/d3-array': 3.0.4 - '@types/d3-ease': 3.0.0 - '@types/d3-interpolate': 3.0.1 - '@types/d3-scale': 4.0.3 - '@types/d3-shape': 3.1.1 - '@types/d3-time': 3.0.0 - '@types/d3-timer': 3.0.0 - d3-array: 3.2.1 - d3-ease: 3.0.1 - d3-interpolate: 3.0.1 - d3-scale: 4.0.2 - d3-shape: 3.2.0 - d3-time: 3.1.0 - d3-timer: 3.0.1 - dev: false - - /vite-plugin-checker/0.5.5_svpeoejlom624h637oo4yy72dy: - resolution: {integrity: sha512-BLaRlBmiVn3Fg/wR9A0+YNwgXVteFJaH8rCIiIgYQcQ50jc3oVe2m8i0xxG5geq36UttNJsAj7DpDelN7/KjOg==} - engines: {node: '>=14.16'} - peerDependencies: - eslint: '>=7' - meow: ^9.0.0 - optionator: ^0.9.1 - stylelint: '>=13' - typescript: '*' - vite: '>=2.0.0' - vls: '*' - vti: '*' - vue-tsc: '*' - peerDependenciesMeta: - eslint: - optional: true - meow: - optional: true - optionator: - optional: true - stylelint: - optional: true - typescript: - optional: true - vls: - optional: true - vti: - optional: true - vue-tsc: - optional: true - dependencies: - '@babel/code-frame': 7.18.6 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - chokidar: 3.5.3 - commander: 8.3.0 - eslint: 8.32.0 - fast-glob: 3.2.12 - fs-extra: 11.1.0 - lodash.debounce: 4.0.8 - lodash.pick: 4.4.0 - meow: 9.0.0 - npm-run-path: 4.0.1 - optionator: 0.9.1 - strip-ansi: 6.0.1 - stylelint: 14.16.1 - tiny-invariant: 1.3.1 - typescript: 4.9.5 - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - vscode-languageclient: 7.0.0 - vscode-languageserver: 7.0.0 - vscode-languageserver-textdocument: 1.0.8 - vscode-uri: 3.0.7 - dev: true - - /vite-plugin-svgr/2.4.0_vite@4.0.4: - resolution: {integrity: sha512-q+mJJol6ThvqkkJvvVFEndI4EaKIjSI0I3jNFgSoC9fXAz1M7kYTVUin8fhUsFojFDKZ9VHKtX6NXNaOLpbsHA==} - peerDependencies: - vite: ^2.6.0 || 3 || 4 - dependencies: - '@rollup/pluginutils': 5.0.2 - '@svgr/core': 6.5.1 - vite: 4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a - transitivePeerDependencies: - - rollup - - supports-color - dev: true - - /vite-tsconfig-paths/4.0.5_typescript@4.9.5: - resolution: {integrity: sha512-/L/eHwySFYjwxoYt1WRJniuK/jPv+WGwgRGBYx3leciR5wBeqntQpUE6Js6+TJemChc+ter7fDBKieyEWDx4yQ==} - dependencies: - debug: 4.3.4 - globrex: 0.1.2 - tsconfck: 2.0.2_typescript@4.9.5 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /vite/4.0.4_arwryhsn4zwmtf5pq2mmdxlt6a: - resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 17.0.45 - esbuild: 0.16.17 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.10.1 - sass: 1.57.1 - optionalDependencies: - fsevents: 2.3.2 - dev: true - - /vm2/3.9.13: - resolution: {integrity: sha512-0rvxpB8P8Shm4wX2EKOiMp7H2zq+HUE/UwodY0pCZXs9IffIKZq6vUti5OgkVCTakKo9e/fgO4X1fkwfjWxE3Q==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - acorn: 8.8.2 - acorn-walk: 8.2.0 - dev: true - - /vscode-jsonrpc/6.0.0: - resolution: {integrity: sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==} - engines: {node: '>=8.0.0 || >=10.0.0'} - dev: true - - /vscode-languageclient/7.0.0: - resolution: {integrity: sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==} - engines: {vscode: ^1.52.0} - dependencies: - minimatch: 3.1.2 - semver: 7.3.8 - vscode-languageserver-protocol: 3.16.0 - dev: true - - /vscode-languageserver-protocol/3.16.0: - resolution: {integrity: sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==} - dependencies: - vscode-jsonrpc: 6.0.0 - vscode-languageserver-types: 3.16.0 - dev: true - - /vscode-languageserver-textdocument/1.0.8: - resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==} - dev: true - - /vscode-languageserver-types/3.16.0: - resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} - dev: true - - /vscode-languageserver/7.0.0: - resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==} - hasBin: true - dependencies: - vscode-languageserver-protocol: 3.16.0 - dev: true - - /vscode-uri/3.0.7: - resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==} - dev: true - - /w3c-xmlserializer/4.0.0: - resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} - engines: {node: '>=14'} - dependencies: - xml-name-validator: 4.0.0 - dev: true - - /walker/1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - dev: true - - /warning/3.0.0: - resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /warning/4.0.3: - resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - dependencies: - loose-envify: 1.4.0 - - /watchpack/2.4.0: - resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.10 - dev: true - - /wcwidth/1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.4 - dev: true - - /webidl-conversions/3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - /webidl-conversions/7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - dev: true - - /webpack-sources/3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack-virtual-modules/0.4.6: - resolution: {integrity: sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==} - dev: true - - /websocket-driver/0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} - engines: {node: '>=0.8.0'} - dependencies: - http-parser-js: 0.5.8 - safe-buffer: 5.2.1 - websocket-extensions: 0.1.4 - dev: false - - /websocket-extensions/0.1.4: - resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} - engines: {node: '>=0.8.0'} - dev: false - - /whatwg-encoding/2.0.0: - resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} - engines: {node: '>=12'} - dependencies: - iconv-lite: 0.6.3 - dev: true - - /whatwg-fetch/2.0.4: - resolution: {integrity: sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==} - dev: false - - /whatwg-mimetype/3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - dev: true - - /whatwg-url/11.0.0: - resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} - engines: {node: '>=12'} - dependencies: - tr46: 3.0.0 - webidl-conversions: 7.0.0 - dev: true - - /whatwg-url/5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - - /which-boxed-primitive/1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-collection/1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} - dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 - dev: true - - /which-typed-array/1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - dev: true - - /which/1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which/2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wide-align/1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 4.2.3 - dev: true - - /widest-line/3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} - dependencies: - string-width: 4.2.3 - dev: true - - /word-wrap/1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - dev: true - - /wordwrap/1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - - /wrap-ansi/6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrap-ansi/7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /wrappy/1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /write-file-atomic/2.4.3: - resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==} - dependencies: - graceful-fs: 4.2.10 - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - - /write-file-atomic/4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - - /ws/6.2.2: - resolution: {integrity: sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dependencies: - async-limiter: 1.0.1 - dev: true - - /ws/8.12.0: - resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /xml-name-validator/4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} - dev: true - - /xmlchars/2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - dev: true - - /xregexp/2.0.0: - resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==} - dev: true - - /y18n/5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - /yallist/3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - /yallist/4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml-js/0.2.3: - resolution: {integrity: sha512-6xUQtVKl1qcd0EXtTEzUDVJy9Ji1fYa47LtkDtYKlIjhibPE9knNPmoRyf6SGREFHlOAUyDe9OdYqRP4DuSi5Q==} - dev: true - - /yaml/1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - - /yaml/2.2.1: - resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==} - engines: {node: '>= 14'} - dev: true - - /yargs-parser/20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - - /yargs-parser/21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs/16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - - /yargs/17.3.1: - resolution: {integrity: sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==} - engines: {node: '>=12'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: true - - /yargs/17.6.2: - resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: true - - /yauzl/2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - dev: true - - /yn/3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue/0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /yup/0.32.11: - resolution: {integrity: sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==} - engines: {node: '>=10'} - dependencies: - '@babel/runtime': 7.20.7 - '@types/lodash': 4.14.191 - lodash: 4.17.21 - lodash-es: 4.17.21 - nanoclone: 0.2.1 - property-expr: 2.0.5 - toposort: 2.0.2 - dev: false - - /zwitch/2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: false diff --git a/airbyte-webapp/public/cactus.png b/airbyte-webapp/public/cactus.png deleted file mode 100644 index ca452bd25e3ceabaac85a0cbb061cd49e6ab727f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17018 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∾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 diff --git a/airbyte-webapp/public/cloud-main-logo.svg b/airbyte-webapp/public/cloud-main-logo.svg deleted file mode 100644 index 8987b1b4d027d..0000000000000 --- a/airbyte-webapp/public/cloud-main-logo.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/airbyte-webapp/public/connectors/google/btn_google_light_normal_ios.svg b/airbyte-webapp/public/connectors/google/btn_google_light_normal_ios.svg deleted file mode 100644 index 032b6ac5f761f..0000000000000 --- a/airbyte-webapp/public/connectors/google/btn_google_light_normal_ios.svg +++ /dev/null @@ -1,43 +0,0 @@ - - - - btn_google_light_normal_ios - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/airbyte-webapp/public/default-logo-catalog.svg b/airbyte-webapp/public/default-logo-catalog.svg deleted file mode 100644 index 528e851e8ec7e..0000000000000 --- a/airbyte-webapp/public/default-logo-catalog.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/airbyte-webapp/public/empty-connections.png b/airbyte-webapp/public/empty-connections.png deleted file mode 100644 index c7db3d284e028bd87310679e81ccc6c145622edc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 250324 zcmeFYcRZEh{|79QRUCV-qm0PN&fX~_DI+T*E62_r5jl3EYzi5b%|Z4i<0Q&BvN>dD z9301auJe68-|zGP^Y`zM^y+ZuzOU>0eBSGG$38I7xkkxGNkl|+P4}+mLn0#59U`L3 z1>{%2Cs&4a{(`?KJnx$O5D_umApE(c`|$c6`0$d?LmhRZicyXY@DCCvHGMTAqUvO- zb6ZlP%VRFOnre>%E^XzK)^TXfyrwdrWwN+V5~E5E;i>9WfBAu;io)G|R;jU>%>OjS ziie6yBx`}~`Wpy28xLgm&$Ejl*JAe|*PxRF8o65MbK$XhKL3=q}!o1pJX4dIj##hxC@)P@=&?pVD+t8B{ zmT8&xS8rleV*)U*U>;L4V-8y1EBJ*M5~a+Id~{P8&*o&!J0U5wopiKxW4rHWJw{Tn z*!WpY_#iC1U1b0kznpUm)0FRx9rEJ!JL`>5@y^d4)T1*EABIVOd+?!!d*<_nV7us#4mZoi4R}7NGvY=&Tu-S@@g07!XFzz9zq^T9s!T_$)ai&Go5n>;Q0H{;SG*m6Y;8z#bZ(~4?l}H% zk)vsHeQ3iwJXoUX`A%>?8WH_rI56{<9$h-^ggi2Qr43E$e@s@npXrUq-@xojHOZ7` zrrE6_2P7EiyW$tIcad*HLRKQ$=j3EXC{IY^kUo{26HVdmL!nn9@}FOf&pyvbTjTrm z?ikKz=uW1#JKf!5{_o;FA&8sF6l)+&bGnU{`!u9a~TX? z%sU?^+Hj5H?7!=vNe^AL_LZ6&VossEL|@Hp8zz*>s7L#hR)JQfm8{y?vSkYXVfz4X z8p+&=Lx^kS~`(av2SK3 z5sZ2!Uw0jAmRefkq9Fx-=kK2ftkGXn4-#?pg79ic*f8ma-W2&CF#C#wOM|;J_&yEr zBd*nyr)NGAG$tR@&2+0799~H^biX*^v*5Ce6Dk%r)|Y;V#f!C{+g+R=AX|{5Qsa7S z==^ZM-P6h99PfLW+-ax$Kj&wgm224^Z4#2Ba)qchW}6V(i+}0u8Rm|ez2|$~G&}V! zCAq&HZnHLQZYV=L5I-n0e4??XQHR~{=g$2QlMw@#JDMi<%#{^ch+0li0mgJAB(QQTn&IeSea4W!u?j>?l|P4<@sxmjt51aYvJDHV4(DNO&!$@^U3CECzGJ zflXLPN{>iXjYKm&8EC=G1-pkgS<4sGD4%p3G2*&Bs^4_TgydI;yT#yETV>}%YGG`#G$d89I-PERk>Hi)N15hLVf+Lvx zg;bP(l)PrkTx)Q)sMR+)TIxl&B>6SZd^PeFpFiJTNZuEzj$)N{&p8DvlKY@x$}V1h zKLvRXo(s0b4uyvE{ly!o&INSihK^6HG}YK5xtGu_2cw(T zXrFWHN?t+YC2sYVE-JCDHvCe&*d4ElcH{-098?_&@&3BC+s_@&(X7gob$L`MDqcQ; ztnWSMCK?~|8W}9+Gpf=hQE+FOcq{`cF~^!3k}lDUIZ;`XTh5Re_J3JD;vrEy%{7mf zZtM38NZiHl5Bde<_qFYP>53@sLihV0mc<6ii;o?(fpLeDpmocS2s-(4C`A~HiZPRd)UPtey= z^=ma~E&rPFtSy(#3#l{wZ?%ur!D^EoWVzkU2}2wqU?!=zPBPhgv`BPGZfm;sxc7+s zd@Ay7y}+^T(|hmT#rk;F*dK`*v1GfmKFDp&5ob2)1rMzcH z8W^QB@?={vks7%UCpl}xHmSy0P9Iv1Tk1H!_v$WeIBc;gVee#6AfJK5Uq_4iBu&^Q z%J4Wd>=;_!Pc@k!*2joj!A98^8K&EW1^QFVGkdh-5cKw^S3{#r@1RrLc4q3oD9|Lp z6bD^INUFe%Lt}wMNm1wJ{$&3-d;)ic1>58Y8@c^44e37SyfyVRc??@qTweWl z5DGj*>p<{-dvw&@*fdrnVV3(VpKXQ!OS71BP}=-Le2LERB-d|dFtCHq02&5;!0Q0@ zTdGe&H#3{jmiH9(MwH&&WG00iwk#wq7}`V{3Prx$iVp4xRUUdSrTpr_a3qnPc>YIT z^;#H{?#XELZrdgkIb2kAV$IU)A^=$eS!_6=CYD>elYby&I3;6uV?$GpDct=uJ=8Hc zB%PE~(=*B|EES{M-IcL`mr@=IOXgCVxh2SBebC0-F)bE0ULx@^|0HxioI@Dfcd_6# zYUYp~;@@_<=F^}2^1J^!dmHjN_ILraLDpk(9I?B{n#JsV3RCW{#x5UjWL^IdFL-fw zL=~8z)W>YkEf&^Cy?pv9-P)D@xao>b@OC|7^NYbo;9f`gJfg&{8R=lW^@iJKQRTmD zrb$^u9{WVR2^I=dm_ab=-|L)1r}eY5dOZ8rQ~B-hXUEo~-#&SV1*dydq}EZzfh|NE z#-&m7`vrazRMWu;e7@LkmoB8|bXYJ{a$ZIZZZXKcHcVIYPI7XWFPVd5>|6hS2%c7gMqE_VDoWLLC}(`EW3uA;7%jDpjo&Dk^);R|_8vQ*3+ACG7he zL$Jz>sfNql1*Tn(OdF5epQHXDtlVo{d?9=LU8Y*@|3$^mNvY6YDoL1dFR`Z;^|7N zXnUJs?_*y0A$QhSPkc4Ze@3PYk*sGj`#%z;`SQ`j6b8*;N@Sk1MZHo*~$W<9WsQK3+e_U)baWP)qn3f@U8@- zZblcP8^&&j8h#fR8?y51$~EtDkNGyo_vVfgU}v-FNzQ3h&VRJ*_pw(59PTZ4j{tDm z*2FQWE0enI)@+BMtYyK^Y1-eehmB7k#}5{VW{Y6hjGh(I^zv<>XPv@Fq&f1!YHwXN z=6jf#^_0Q#j2AOK=!43DPM(bBH*Mn`<4Q8XC8vYl^F}wnCA~Tr2|Pqo%ZY^#wvIMs z@?)B8eDZIhaJvOf&FXR^~ukc$J|+loz3osq+x5x2vu&pmvRXT`Q#*!DxCOj18i7rpb!wMo1LbbS3^da9oTsRi;;uTm zq8@Xf5$W8R(DpFgjN(=_M7@r>Xo~k8b>P34YwQFhW))ZpKl)`VDjOF4<{p{@B`TE~ zMFZBe;7LXUk0SIQR1|9BCu_dwWw#?)gtHvei{rmg!fyaw^zXu2IJDK z^bmcM#7&r!Iqs&{1F;`Ytt$3qkqsWO>=8t?4^~wIBkO~AQdtu>uTBfqO3-=~DuBV( zt{@JA-7U`X$l2rbFhfUvirV%y1m0!Gr>N9E)73pOw=gh zgFzT7{1`dVR*g4aJ>JI5R_kXgBmpv;eRFcxXZ831J)mruidA}eX4GA7x`Qk6Mw$2N z(beMzwkKN)WHJ&>_2fUuewAXBx&z`Qk@_)+Dz0;7Z;)5Qe z!f^x5keylAXzz_W>(+#IcRTl9M#{75AfGL+> z%R8A5$F~XxVF?t_uAxvT+0X6*^lpnm{tS^hXA~)-)v<g4RjiPp<9KJ2d2$n=Fy69(^E6Hht8BiuNsR=~|BJJn@)(*!FWtD=DrNVKWHt*W4$$9U{!!aefepyX`*p5uv zgj?+_>y_^P{5IlnFuz=W6i*Af+O(~8WQnf_ib=|R{{;mq2&m{=1!7BcD~=D(SnQ?H zj0KGQR7BQ?XuJr=DLFON3NC27Px>)DXHdK01kT39xF=$36x%Dn1XCV?1yf22C8j{s zeFbmZX-crLM?J`Uj;bjhHp>k8H)wSy2dI#4k=DbX+5k-U&QF$;M=#^Q3s*{kURV{l z+lm?9ZO2>x71nFp``X-xsMYiPcLVJI(f(YM@~07Xe&MOgr!@twm{J<0AE4v2C_{Pv zzCgCCpsknlUcJP>9-PT(QU2{v=o>(T#F^^Lz}^{}t~R7JcBDeoudDSX!C!e*r@_)Q zzxIcYc}42rLJmfpsPC-v)Q-rYGR&QFA6p-TrfbKWI65TO?&jXK%H#v2LN-A&od3J8 z8xzET&ve?a6(*MT)jtiQ4*zZYeV{!6S!rKW<~E>ZFdEphvHxL`M1y=R@8rof<&w5a z*$7yizw!}%2qz_*OArLt4jiMAzs3eaTFDTo^zE0L94k>h<6+N@?GlFNmJ^BrMy&PF z8%ik!9lm)A>ZAY~hTWDGn4#fTo}CTF{8^v}_{?R%1gL%IMb4i;NC z1}&1r+Yy6Iil4;M{~X^wu<_4mhDZ;$Gdw9Vq1wyxFbc^3W(68?dS>YH^oaj_D0&9S z5&H|U4G35#kdO8R-6;9%k#SQW{`8u1H#$~xSz%mXHWw=rKh@ILex5YX)UJc8;to6M zWDId)9}8XaKxiCbS-9*O+W$CDuvhN4?lqT3swDR&jbX+ZjP-1b^MYI_k!|58*^_}I z82Nm3$WQc?>v0amjpJM(S~^~=t??9``Vn@I7TY%5u?0rCy<3L$en`I8 zz^>oM&)#h^`^-}uLBHhe%k?$P1q~^J$K6rbx{U3@pK_kT?Uyl4TqlY`v>U>GQtkc9 zq5HkeI|?D`?V&bA*v?H3|A4Ub=lUpKel5d(n90Izk!ym0;%pf!xZQBPWV)qyY~aNy`u?XM z9~)}GhNEO`a-O@FJOP13VpGg>6kSr(!5n;pr{pK z>6rO!Se@$Dil)BiP_oL!6h*nuutW^K5bgEpD^NbW>rlP|!Fi2!&4iU;0`-p<)Hu`} z(5%y(bz(oy-zJ*Zk<YD5L%-9omg&Uhuee1I-R_B{{{w_D z{-2UEvVDsgDuPXP*0b4@B^IwjTF*Y?p5~v|_)tu9!iA1(TTxP-U2TB)OeZlTu3~B)Z(dlKR-Ph+iFT)i7Y&6~Rot>dFS$nJ%4@=Dn+-?0!*Id|H zP0zXJ4`>;cp&vN+tk0zWZ7iqYb6|yfzuRs!C>z}LCF;5m(y)VT!EJ3?DDL!pilRb^7 zD^su1`Jj=5wjo*4Vlwaf+IIGLbd#MXP_b~|T|2}+32J0QPD>U~1V4hG*3t55XY4Qc zH)~xF*l9w~^qdo%oLeJ?3W1vkeDFgLG#f^b1ZN9KOPZq&+#oh8cu_4nd=7CVF7)Mt z`XSNgVK>CIqx;blfPAH70h*lQ=leUE-796}9#e>>L8kJ@X4L>U6&u}=&ro?yGO4BG*Y7hK;Ywu)64JFoAB<>YK)p!vPzx9V)-CG3D&Ja zO_9}`70ngccI5NKfg2t{yqdKO;~OVzY%70tO8f2e`$DhLa+ff8Z>a!>asYFRuS?*yf-&e#5k!`QR7Iqy3KvV#R z8s!gvXpDd!-QAEGB`!bR@6a0zs-&JQ`HUWhQpVulil={gAhO|+r1@Fe&)UCrzB&8LsX=G}yn;-jPbd}l=WDmUP!*EX6L)M_ zK8@2BxV-V4Z{qb@DdgW2GVXYI|JJjLmVftZf8G;jC6p#D&pghnpVNsecuPXIDYirJ z%Kn91sy?0{d@m?N?4c*31cuFYqsG3CQ?Lu2Zws}`8X;ve>mcx3M}Ro*by^|nj|M8+ zFaENzLIw&A=gt9e_0Iw}v-Zx^+RHAClHB43%|*Lg@NWmw&^Xk+9_E6Gl%t72-l7-& zsMj+lZyLkC3zbMY<-T|?Oex3*ay?BxwUa&f=50qn_}=f`Qrxvcz{pT}lAszsN1S$j zM{Ikbp73Y$3oxxw85=6q({BJm=tS^2B(Yny?1Z(9=t2}tek9*1OjdTa4%)bZkuCG{ zbku$GBqrwse!T3~odJ?Z*`tEAdphtd8gXvuXD+A;B+jD4t#-t5r{%z4yxHG_aGIpp zR*3#Mr0Ne-iM2r5dZS)h=1q8<&Vk*$+pPym4>iYc5r7Z`4tV^3G__efXmnYuPB~+Q zz9I&0;+TH!1e~6hgFc;!es(-?0?Qr^pfyyckJ|>1sK%I-Hug`l6TF#&_d7K-X7~U>TMI0Xw9}&s=k&` z)Vk{RS$_k_=01X(0mJX&ZJ@9%^}#@h}Yo+1RZ{fiXSdT;oP61NC?RG&_r@N zka#I{tO*+JD0HV8yVKlEZWT8|$s6U&0r@u{h~^ZSOXcSF2!Wb}pKX-fYcsfnLc`eI zQ7}*_!ih-`&X-ZxQC)x3PAx32QP$MVmel89M7G)PA$T%PzE@Af$F!I;!S>A%QjtZJ zA)zV1J_rB5AhmSm*_2-@%!dIBY1(R-^}g@ZNy_{mxlmsP?v3IE(A3;Fh6W)!AixN1 zxL^H>UazS#>#O9|l5JsUK6?F5Aqns#h{fGor2!RfYDpeYPc}=3F;xy z5NH(XsFIt)Afi`aPgCX~643EJ%b<-%u4+1gg6pM=T0IIeA?JNUvV#^G7On1~E4FD5E7nQoA~Nf42wQErretuE+$`J`r;CQZa~(E8v4X zP!c02`^zJ*+1*Ri^wi;5oh$Z#%SvSUv=hYJffzX~H`hOI@=rJV&cPe?(%enqJHiT< zEfYd7K%mimIe}}Lj_Fo@5&#lv2}(T3v%UXgg++tAL5I!r^7>&=#asWD#>39{`y(r- zWD*C17BJG&b!jW8(>_Fv?m;wU@QvN?ri`Bs-A^ZFB)FubI^2O7O!rXBs$=}3Zrnf; z6n~RNXZU7$Lyo5kX4VJvs#4Mb>Jf$AmbF&QoFoX)uFX3>KI2Wjw#ldtAHAxMvqoH# zFyFsHLz1(NK#hLt8_mjgjmXj1j-S>?_*$TXJyLw-= zsipu){FnKq~*PfXzL@0W&QuWNdIE8%d0hd zRdQheF}YE2KryFh$0f%R>B+0}P~8KS#D}DmymtiRr~P7JUour6sO3yM7bXrfnp!SW z{$$$!3??wfD0t6YBS@J%rD@A<)Q=k|FlG-O?3s-s6!Z}%r*E~t6+#|=q$>4M+o_%k zk&9BY{pw$rl2n2dD#@|S3%>{?gsSpl+qh#CG6Y1g#nubvD!%IvK)Bn3m;@Rgsr+0M z#*>fRtZbhV7VRI#b#w0AG7M#%c}omDg&9L?sEldjsU3)oHE=(|!ps%nTxRFld>I_aP7HA{|Y6 z^9&TGPrP~=*}ER-H0F!js?R+~Dq(U0LA%#)Jz0$59xgR1{AaE4fZwpD^qNS^IWQ1l z;mF%VB3^k_z`8bu&pv_G|LW3mDM0$kXff4*J0rEF_RNI+>6ZQGyJ0sfkLK_JMVSp+ zOgDgC$f~N?$Cuk6bpD&ieK4xvQJw5pzpaO&uG5#Fin<#CfakK1_nO%8+C2Wkf1LaQ z55^-LYccnHKI9~X5%g}^+n%m1nFjnhp5hh(cFiGspnrJz z07oRdn_A(k+2L;~#5N4&qHR>EeqFsQ6#dcJcBZU2>-(_uq-C*@ssly*%3D6AtXFL& zA;73v1EucQl}6@KSYg%t{_}fLx;?;uGfizm>u=fFWw{i4q0M}$OL_OfvovQhCU${o ziKU0KT9v^m(aN?dX_0>nRd96{QcCL|URkCMKY3ohs^~HohJ}smL3*W~e|(TLeAu#6 z0?5zUHxWA&1k98C>$sQ?+AO!q6(+FRCvZ>B+YWI0U1m$qPB~PzA_g_%S3UUKDuqi( zlT^<|(xH30aGUIGPv!A`7AJ9P^o|Y2A-3~+laMoK1(7bS1TKE z(qC8EWri8~Kr%Z%LQEy{^ljvNct59q#ygWIgCaEp&|{9Tb! zo*&C5j#HKkKj`;~#sUt<(@wG=TKmW<>8OX&&m*oe zRNRl61|-6j|0(n)boRi5LA_bfc`88>5H!d9&||Nq2|^FLLc^6~W?6`&MZ-0DFn|oZ z|Aj(+s^5W%o%4RE{-DbBI3@a`IGiQsJfA`eO%rkYibmNp-X!7l(&a01`_1MgAxW!X z)J2xyv(U$YJXX4Py&(SEl2*c(d$#8}o?R3bo^zn@Y?7SUQ9a-4Z$js7cFCD%ES))V zv%4(Tygy-(CEpWSlc-=($q)G#+icnbTK*dFk9{MRs906Q$M1Dw;7^>3ORqD%3amJv z$Kz}cpYc<#G^KlrMLA20Gwu1Aqk4)47V`$|f@19=359VJzFy#Yi`vwg4u6Ua&&i{Y zK>z%V$hAZHAwpdM7-ty6_)K;A-Gs~Q9`?nVWoj>h!!bInfGrC<17PX!;CO7SwHJFvrd)SxAp1$$xi)kNah`Ykjtp>|A z(9uVVRsla4@&y(uY>2WV6C|m^#?M*WO+NUxKV#;+?Uy2O0IJp%4H7dT13&YnLiAOo36U__xR zwxtqxy^~kYW!OR9G&&W%xR>EBJI(O}RQSCIQ_D|KX0ap9yCd@GoE_G&Eu=Ci@FD&qGGqYn z+snxw3bxWFsxtVKeih3)U8T?r6Y#DM{U3`A+Wt=#m(vPf9?PE9q`P|I^;Sh)xcT?DbLj5aMlGXYVrZ={4gDk$Dv40t`lMx zcQ3d-eoy z2)zESr}(_kV{;#nUT5oYhfb_sHN0uU{Hiy`G1Ix$xvMF;t4YwWB2F!i`C(H4#0oR> zTx^nA*H$5-di|%m7fj}xC-TL>QsTT#RG_Plc!kQ@dSTCGkc3&!>a4`5cwJdUO&{Cy z#^)JlB(1?189)`njelD%unGM6380zFYU0BMRoV3l3G+&BuG4OOopvN#+x8`ZMeh|7*t~?Z6sN48%CsU2V$`C%lhLEw-wy z7idF=CHhxl{m3f|wG+MN$3I6{BD-T~!~!^tSZP~L-jJOkQ0_i+3k)GWREm^bH7l0< z;qvrCEoI}8f^1gs5Ay>lc_ck|dQ2`7gXEW+lF9S58~YVn(STkv#E-@pb zVLlAi`o74KxXbsDtHbWv7?n#@aMbz(PsfkF%!clo5?MHnDuI4HxbShRSFhLY;whP< zE0Co?>NlGiihHwUUAvvU%A?noiFdbBw%zx~9f3CIL5`iJDFUR2vmzqJj zDeO9n)hs-|=QZ@$#Qf9eShBf!FBb<$6=9aqm}(FHNnD`JXz#Y@dqgDW?qmeB;F3g_ zIh)t}ZB3;e^Xsa6_lcJ;?Ta$(&|2=h8P=9|BH(XTr}~0rubsybI2Bwpvz_ zcl%2@;>o9MFH~&YSIx>I#>)N1zHz?UN-#LuW*Z$G=e?Y%o~FwqBS5@+uR>+#%d9;} zu_PK!)Fj+10-1ixh4ooU292A3zb9P2^3ajC2@=81Zfp5&wVX~J-uH|`QfOP1OD^{5 zeL*b(`%HQ%f5lHOi_DxmV^V7#0W(I;)ouHtT+yTgnyGw%e5y9Oef69#U98zcB`NGU zySL-~(kZ)M4cw#5El13JFX}8ARCBw=i*~B-Qd*h;zyy1Jm37J6us^mjpy{6i`F23- zKh~s_I{ALC;IGpF_UMBf_#A7?1wX2qQ;>gJR6bw>CYLtf@SV-C?gbgzkn7(gf1R3I z2YwQjZ&o_Q8|iSaCLIm%C4Y6c8#4O_mUDyv@FW`@CxTQ|Byd2U_JR-TjVL(83U1ny z7}c}(K1vdD&wuq}pvJR2s)(^_qhCCfhG*8N{0F{1YF|yov(mOYqE|cY)$``J2ZKim zo+{oe19AOrmFNzyGl?D<_)S|c3j54Q_FlLd)`cMZF(_oG8HK04D-tM zl~ezP2r`pg*M|gG@5-7gfl(ish&FHCX8yz(Q8%hFT(mBs)lF#&ikC@z1uZL4=KX<9 zY&1xtEs&%HH2m6aX%g4CPfNVHeVbe!!7U54&V>;5;qM;OWp~@~7r{QjOU?SI5%Ucn z!!vcXjhb|;>b&9zIJGQ+`~!%7K11mUUC9T-8wN$)2MU7)lrG5yTK7Yf{uYSIs4#S-_ zwP03xCgo1gz_4TY+x+Dd+6O{O^1zsAKDd`+_*YH@7&Pu8HThdAcF%+Uhx1xgkAn|(e?F5Sp!xbuQvh(nfRu2S2)OQ*8 z$SnmvnQk5AlHRvAB0Dbv*=6M`s^|T5EfGtVzdhgH&VHXmING1prf9X`m^j`e_i-Ir zh0@t!I35e=*_B=nKxDJny$6imAUa+?9b;++qCRTf`Nu74`4tEz{O1+2`fq#IvqOk6 z1g^i-tQ-P>iy{Z@&JS80U)oY~B4q(5^k%P7t7lBW5%4qbEJi=Nquc4DC>nj02J%z8 zh?F+~ctn!;v&nYKhfO?8DbhGTst4<$n*(2_20 z>rO2&b4#@Vn&ec>V4>l?MDHbeY@hlA^7f%No>9IDKM)L3)EC*Qw;Tz5{;AC?b=hl@ zzCY`c6m>s!LFkO~a9_<$)_Xebpc`HA+v*|cEbTO>PBQRTN0!&xbK@WFZQ&5?DYf|M^eC`rtPdORT%Kib zB&!{u6-pbHd}}A>o5N404tI>gG8f>~7ugk=t5lwIJ_hoVqe{N|d6iZs&F$m@QHBGJ zpS(*VJ;c_+B^nGPq}0{|Ii8X1m4uO3Igc)dRA2c*H$F>?`tMju(@r z>;rD>N9-&$*%sq7SLl;c*Ks+pQc~t~Y@OPnK+tPvR;E|qZxM_8LH1oNu?$$ZX$G%qGY>j~#M|+&y z{p$D~w#z9B;S5ZwKIu3}4wlQy6nQ$n6gNsW7U!w|RK>1YoTiV9|80i+6)5h$SnCRh zOqFo#+qIy5ANdMyjzzfHBypbeb+bq6e70PSzk|Vb8!VDwI7cwxmTrWV4K`x1IfmkXzZ^r;`EXhk__ zcnelOmYm$?I`o1@A+7RB_}#~Xi7~Ctt#3vtG0&L9BHPSH9a@9i2rfg&f=h>n?Czy5 z9~ujRMEiTeT?cV+ojhYrVlXR*6J6zykvU-4B6GXMR37--?u$3K6D_v_bqvMDe4YWn z`o!gS=V;vP^6vox4>O)$LdSb8_sJUu<;Zs^ct<7K8)X%Mz~rgE zUu_(l&LI5TmW|H({$=Yy<=(4L_a0~8E22AT1!+^`y#ucTrAQRW1sA!t>i5{zSTgq( z|0I84Kibkx)8P^2pY;jr(h?gDls=ubpy+eErMP20Kv7xl%2aBm*P*&{u8k2+>{r6R z07gRdW*x)W^Rg+wy{s8O6l?_O2y}t8>msY}6aE(3P$jY*8kfJ;b!<7w&Ps1Ml=Nk+ zMp=NLF+z&K1@Svt#~e@{KPwFSbf72@y{d$nT~-vOWs3c*ktSlA#_3_#60cj`VflKg zS%)jop*Q8Tx)hxyl^k{TQ)!TR$&%S7&{dI$>SaI;Dk|mvhqHML`Gsi zz|HlrKL1F>MrO^jcvIS%P4WEg8Y2xA20C*fe#0RXHLzk@C4_%x^B$K3Uhr39wi`*P;gw|YI{`yuz7vC2+>7!qTlUkCY5?;ix_y>r+ z*!cPB=Sbu8JS`2V>(bNCm|#kwbQWgtjtrmt4ya201_-NlWq^@aBJD<}x?R0G)e++f zj6brY+SIte@Ev@AJ#)HLwH#6)zj#p}b^=9C10QL4mDXJ<05R{`ea&&I%68O*oRXfO zcsDo;iN2-q)u-e9wH7xts(Kkd)gco?m}XK;SU1g4@qFD;484gMW2y>yVw|+t$L`^K zgmPu1KprJuCQA{VxWxCwoVK&TsB;>kPX^bd=D~GDAaY%6sLRxS?+{dwwX6gehP-bC zy7JUFMPruP;*jSJU((|xtvz7eHmH*Kz%A?(rE>zZNfbi{T)2bqHLbu+n)=kQOMK-9 zsnKBbj@r70uf_urC%3*&XR4*b=xT)!1&>M!Hb?&c|19*7_ zIv5p&QU(I|Z<_}{y~Z!>wi2;DA!sLq7n=6$Q1ds_I^lr}UX_ciVx2s^T! z@&fxP{>Yi1%qS_B1b;f#E<0}7 zUzQZ(KjNb$E$W6sGrfBD1FNm!j)l)BD@0dW%U)kb3sQ!{oKYGGoNd&)0|0czg`egh zOuRG>Pm|d>6BzzwFUPVm>PrONy%oVssvRmJKC?GUt_HUTNtga7$ooMLQsGW&CZbW` zVfM^nxq6gaHg$uSdG8T@OdPx~WY$5>e1n`;AF55P&07|DV&H4HN)_|#exra$(g7P= z75PVa#!*JbzD3a;b;WDp{@vGP^&Y)R$Js}UB)=EY6IptwNV{sh5#aEX)}Q+GzNXW8 zA1-V?+J=%pksPu}OoDngmNY@~j)O1Nm(rsaQVr${6e@+=L;G&1la6V+^n>VshYUMx zwmZC>W-mt9T4-JYDVSbxMEHT0^<*ofE_(7gso!-2R?RXnhKh0@HPS0xnbVWvN@64b zs>r@yth3U`bk{h(xNz@4xCad~zV9Q(RfCtX@IYep6@?h2R|34UXvp5HAn)kyo>@4E zku6sQjasLmz#z=|($E_=anQg@qlsS>iRh-r(*;H>od3|E$pkZoQxqo&v^F-v<@9f3 zmhHpte)|=~l`VF2XkXm)ll$c|PIF(?uayqfH=}U9sd=Y2ph^cbtGZ{8LnotiHGrE2Ay&Tw4NU7xEf34N&6 z45vGJ)B!C~;zFep%Up$5JwAeW0b3T7_;q7Ayx|80`c&GASbD~t{kBiyM)Heo8BX3m zW2s+rmnpCJm!=Hv|GHm?KHv9DI*3~99C0Y%5_kDPZqOK@HQ>^uxb;zhs?SI1->$5% zhy$d8UE5upU-*dF&eAhUon_obKv0?4eb(dgH@O~?Es&H61%&>3Z2BVJO_#FctZS-> z`h#i>688O~%30QPp`(EG?NBEsBTC1ZY4EZz75&qEybSSWjl~9_G$P0rvk;67U!c#f zP^EDSt=X0scjV4!eOhBv95-K|4_HpL`hMr(_x&wb8Q!;o8e9GxA!f4ztyEpNsF;kf z$KZ*5X~}s5qUbMuFX#o?@seBVlVY15CO#`J+V4}da#Gb9NDp!R0tWKh3kvOGHQcE) zB06X4PcSCwkB4bwv4rJ6Q4w+8!_I+XRXwcWw@M(hNRl4|$;;m@@4gAwFXd}%ruAIL zhurZrIsQx
}C$;gT1^R=x`-t@c!QO2_Qjwz;6qCV7ZfacER5NzmBeH)@N3i229I zi-c&MWDgb(%l|~I?I|)AXcMaPjbK(lp(54SX+<%KK5_p2yJ{10>TQ8hVplI9SJmRa zyw);}u|2)<$|E%4kkpE^biOp#0yVpUY_ky0*9fg8d`#%M~r56;4*gd)| zLrPn&iFg=JhPvsRy*QnuK^!TWn3jvq@kufVqb?(0QtbD8@3Ob2P?RmTMjSgLdYQ zx*)8N?KNqB!xdjg&>e@(mP-~C$T&Pz``F$-3m=bLV#N{(ohZWqw0t)!lrz4y)ek2A z-v2)wop(Hye;`_w&Bq*QX&Px5dj6L&%Y^|KsXCn1*-$!Mx5US7NH$UzGiYrP=0Ziv}?h z4;g2E3+HNk>-szEPky5o;qoRP)fU;Zd-eTz$!X3>H)9|XvifuFpKda>3OdTF;H%Q6 zMV+`u?M3{vcFOus%pcu+T8b(7NaeqKkQk^3kw7d$U6GGff(F9n0xN9-Ov8?VLPs$qV81GV<-0{=>=5fHAQ zuBxoPM<4)V%|&?E?yc)@feh5gv1!J4_+=-^`r3X+1~CRc4sxRf@ub#0)^g8JIn$v{ zh;C=!{smapkNF0C&F4jf!BN+Cod>V?(Jl%>o*q3%_ThDQe$FQ$-iu@4!c{I?*b`A)|vCj zrccR6I9Z<*z*&W}152LH6aRU&0S$kJhx#TOcBkHMhtkqa>D>K^uZ)5mbX49hx-Q#F!L+g+9^BVo=_9z!W> zJTU*LW}5hLY!izC{66JAtvES@M6XbMgFR!CZ)DrY1_&7s*>B`|cx+9OL=Rq-(IRnB12No(U8zfA03gwo3>$i7NGJ$-g& zb_}C`j!wXnx>>KA1IAa&_WH6vDPGlav%R@e7QDug8xn#bE6^dM;+%iZ9nI}F{#acU zt*KtG>2M(i~L9M+7{eOYR@Ts^ChIXc$I5Lyg+7kSN@sO;Pe63e{mc#AO{); zxrgPfP%C=%(yGWz9oY`PZA$npM_}3&i6gCC^cBI~40U2ja`lg%f6xhSH5K0#S=&U} z^W3KYR7FUvwKAo54H{@~bDlAz(xtuDq8((wGB|fXPt!al*O%!%Vx z=cBhz>~+_Vsn1WqyRTWp@GYPt8GeU5akJ$%)!SMbK(GIc%O;;&13wn?quUJqN4y}^ zaaaUz3I#6T6+v8Ibsz{^w}5iIP~1niQ-9V83q0K+EgIhTwCn-T_P&opuOaP4L*jTZ zz9gffsBK0Bkf?};bFrc}*oQx!RowFq^MU_fEiji>yGK!`icwqp84cmhb9N3Mk8o98 z+~c+9;x>!-!Q4v2m{Gk(ee1DV*U5yOI5_1@=qlcxVl6q;zL6@O6nZK%x#<9Ihw|Ig zi;XUm^Q*~Ho-SK?y!DgyThYC?}e!#RVbL`rRO zdatImrPs;*8ki`f6nQPx9*}7tmR9W68T;Z7_1%}XzP~y>xw~DxbE*nI*7u8GPPoSv z#G2te*oyz|GxsqNq-TsY=1(q0HMj7PoF4-2M0A2vB=kBQn`va0 zOqpvAwEa3(cUQY#Z-HlMp1*}MqGbKVDk6lj8TSmt$~kByJ7+7u|6TxC?|{ni;QK?9 zJC%_3UB}IzFS&rL;XQ{;0A@^xQ>#2fOI7g&$#t~oHzV?&>Tm@YG{HTOA^-BVYXJm& zRbz_jk)P{3x?1FVe8j%bKW)L}0Fgj!0vf}kTNPsYCg-(^<&2f!6Fu&AbBqnzW5rL! zx}Wl8JzLDYnQ&W)CpIj|Rm*W%RU;$X|K@TH332|g)c`W5y6E!{FXl55=x)Rokl1&% zy`-4fMNh*DV@9m__6fQ*_=t-(v{)sbcg7-)l7FOUrm<^K%~y4$*=#O))Qu<7OV^H1 z$2IZYDDV<)Fjxiu21wls!xxp$Q{V?FD}2UT$~xQ#9xY{E_^Gl;0-$4St+^*GEgy+v z*Fs-k5zdfEip91dKG{z@fhV@-MZLL2P4?y&qejAv*r=dsp7G_(xoL(B=L~a z=xyPMGC5^91n^{BOE|_Pcy7;aO_6yl%B0;Jvj69ca0+9#D;*#j&EGM3kAbLr;#z*- zNP;&aJ$GBBTTD+#Rb;_}m+aQzbwb1X2vnQ8yX9d5p zw@Q(^;vWadbdX0zGx@3|JXCI8nz<@?1btV^IA5BSpD(Z_AxvO^ZFX2?->Xiq@8YPp zg@fFKpw(*aUA?QolBVTOg5eJl_(IIpce)|FW&aEc!sLF1ZEGU|Wxg8L?fBrKatl^? zW@)JwUf4&*z8HBplNeRs$r~zV1KNHDjBb^jvcklC=Liw|zZ`JKN(rmNQv*+Ka@<2M zP9yNyNG`77x9NN_5#{A}9X`*MdCa~9INnu7d6BT$2*OuhAN67f)EP}B1U+qb3&~?V zcp(}^Kbl<`Yz|H=Z)3djqlJz4$gV5d@t!((Sh6;v&h9gEN_FdJX==Jbj~^jjm1Z2U zj53t*@MZ$6d`3AN{P`!dz^(f`P|hd_NowbrJ`OHEY#@B$k;)cv`W7)p;C1V8#5jW( zDEDP8jHS%SpTMrXx(o@8IW47F;vCeUe~pl04H*QIf|D71u>%0zDP*HZnZ_vSVQ*tB zRW0W{Q}`S_d>2jWI)0Cm*YC>9_{Z~`fhAcmh2mdt|Mo2 zo5S|g*W<7CBsje#y^Az29H}R*@`V4!J4~GMtXO$y+RIHsPBzQ`HI2D^jB*#2Q1-iL z8-&Ex@Nq28#<1s@_5jm#fJU*!&<)P_;{X~)4VVs8k-+&edwildL25DkMotJms#)V( z@0ggHFQnZTQ$-Ey-$(qA9#V5%7S*bhYK1WXXj(Am0aU+2KJ~lBFsgT+^*wtV^@dMP z|NW?!fSSsiFRH5uaHmSI*{it=c^q*ZR9R^<>PX5c(XPPoN20FdPrPMyFY*U?(^wAm zA5iU}qZvL;IOLz;PVmZltT-%aCQABD*@_U_C*S>_)hcu$a%YSCjCDmpwdc&>ozTR}}WHKb3ti|CfL<=HKJ_tvjoYWsF?&E`aHH zO}rknzIDLGmjl3en=F{QS%ri>71)_2XSlk@&E}-jg6LL!NKe(q(ds*i*W|ahXZGV8DWTN^w_(C z*NIXDQdC~+6LQ1N;D4MCrnBEDf3Lkthtbzh3T&!!tI!nvOk|p1W|Oy(r0Il_{{Y9j z3FJ_!12o+6ty=4Nmwkn|P<~AXiTX>wQbXOul*q$|9Wwn#yOHkPGP)N1`*u5KV)i|T zE;n#*CQ*1>oy2E!{9)=9X{7nABU&wO+;L6;-yFC=(t2rnH2HFd8<0Op*$Dgz{ar7| z-oe-hmzKyqn|6GYUDig@*zb?G&NC6%vV%ON{mLY5b$|uP8-GtyrNaGSZvlxF>EJD- zoX@!Q48Y#61`WO}@OGr|1OQqg4`icrl<(9oPmXRF9{E*VkFmxuka-kyHAnF%&__86 zNnW^7?z|Uq$o{AM8+ZJS`8n}gqnR%b6pea{s?4-mQh}C)e7QkzEnd|$Xo{iq&-%#Ri&@Id&ELX8A ze;TxWA!^EhJa2&4O_}Xep4mGHXFIJ$DKWw`ITvH5bPDIz6A|t>U*Ezkkg?<%{kLm0 zxtb&&??nfBpw2iYh)E%Sx@*q&wGpMP>7C~r6UKCok$`6Zlv!ao0D!QGxiZjF@|VmZ zr$#P0Vr%xy{7)=;*`xdn$GH}LLvv8-gGR~OQTYD^rCHA&p57{dn255d9#?PC?f{+1wwNzkhq+4rOVIX^21wr%y~4Nihf@=( z0)kZXblBH)p+#-BGbg=`>9evjoFc=4fRJBmNnlJE(X?d-t%U!IUAmYHsqIu8^Rsm9 z=l7;(@~{kr3Oa|rg`{<4lbJmszbGRou)F35bNGWEfUBwF_SgW>{s@+jP( zJ()Ll97y43F7H=z00__Giq8bam?&^~Y$h>O5(wu;#C>4C<^6iHBMgJYo#3Ap8pWzBDl>iVT>EjpS8hoxG7@Jf;dB_kV}cO^)V!Vi&%@H z4#dIdgC_9pVW=~b58RJ)mjPa`PqN*SjgK}M%gK?t9O~wyu8u4JhIC&Gt^Zjx58-(n zq!?kM)Zt9PDNmhf1koPpHW=}1>}|tSaSQLV3(k_mrs-dEpdhg~ajSrd#@gX@o{w6O z-jG=A-CL^m+-oaCAR8M^>Nagk3AG>(av9L?ke{giH7kCySSV< zUwv7PBIlUjTus@sF>b%(MKy3e=x4$b>dH*V}A9|>`ND|Fy zRwklY+wnKT?F?{_^(&>=z1ROvm@nw0&t>|tCrO$9mjCTZ7=Wsyu~vJQFyTD#gANA`>{+10N!^$Q*0fspo=oI2{7W z>R#988_qwZ5|erH6COnMxbM_}V4u_&DqIj z@gSeu<~DeD))wQBB@X>AM;adpH9e!Q1xIp4h#el@Q0iY{-R&tGJB+AltJrOO35OsO zp{M5bqS|;vAgkZ(91?#9T3G)0XUz|nxZUYbECH}xJ%3V=CpXA%E^FpCaQ+X+^)MKr(66^EacJyqZTSZ5TJE1ETHx%A!v zukth}L{(XIttjM~5h1tymdQ7=Y_cqc8h?d81_uxaKQ9ra*q2pkiUuQ@sc}JM_uM)} zOnL=W1(qG~lM7U9Od3n4*Sh*|&%pyP(IGyCq5aF0QT;Q1US$a$@cRYSky&#Rrc;R5 zmjwKcp%fZTAqfH@MW{{$4{T}6|CW`esi85{eSXZwa>1k43F{;^-tdNO`f>V%-LjoF%_!^A zoIy$HPHj1h6oZ9?;t^DrpB_&8Mr|9E+Ybo18<|ATYAkz{+C9kN{{zT!|L(78_y`8} zZT?@=1FPTE3!2bRl@eoU_#ZV3ZUX4K8GG(`#LnAffpx9L1es$|uT2+8xMb0#qCdUA z&rGIltQ%w!N);FJ!yiyDbIWG^6XnmTC-|7Q=vAT#D(Au5eT~JYXETbR5!_g1@(Y@n zx{9GzEbFxSqWkNQk*}L|)n-NpzH#)2>ilj}X;NPfuB6&#_Wm4)_kRAmIfq$Hy5cl6 zT+s3WmZM<>4tYRh@}_c;D#aIb^Uysx-wR~Bo^xC4i(EJui_f=YdwqZu=aA?{!>_kue31!W8o8cK*XSgM72H^o-zoBqRcWn>sM?BWw&lY=v|tmFo{DuTP8V!Tmn zpF+8a_S?Ycekq$f$nn504pq9V+|_^%&DO zeKkJ+`f&|jr$Zx|z4olVS!mU&xJQ zaqD(}$+L*#Fzg`t(&%4Uj`SKI0eZp#nZxjG?`b(!kEJR<`)~RC!!JACErnj_(@ZM4 z1xuScj?Hgoi3*jPuoJTcTbE~kK1})YGx71K`-!n65zckeiA7HaqKJ)O{jrtNg7HHJ z;!E#7)A3LT-6(Y;$Er605ZNLb1I}a&rDBG>pQ=F$2}eoN=+U&~Mc^%ZD4=dmr|I4& zM^5XmYc)D&z=2cpeUF_@#%AG^d(OEm?%eyn90i8>4SJhS4QxW&!J;A+qqNL@vULM0 zNhj3OYr{R&{?mz2N*ja3a*hj4h4y=3Aybys^BTDRCyA>jMi{#iWSe+Bpq14buO zX|tI}ERy827I?!n2?lN_GhbcSAe<9ra)Nv2r&iEItxt9%7tl9x&#~J-&EUL2RuI*a zve}o`+i8fJml{@u|4ubES@ZbzOq2#ZVbaR^d-ncDAlQ63_t7o*`#TFIK8mLG7hGcL zrm1MlPnjiCa9Ii+fM;CSdg6l_9i1Pw! zGYfa+6n&c!(LiZdJKSELDH?f1&&0n%30a;Ao1zZPI=OB>6>@mZn@LGU?Jym7ax$&K zOnEC5OK=h>Kqjy3MkJ<*>fJ?d0~Pu!@T z!a8w+Me>86bR-uxa3+3b@_|r~`^*4mj!|&5c^rsTCeg8?-1@bs$p78mu~FNdWYryA5DIV#=FsXMXq=7G0^;!tZ7aF}P3krl|3fFrXBMlE?Qe|!$ zX8Aga)0St89J;jl*!EOybUc0!ePiu;^6r~`7o|{(skrT1<_$J|cdV9x*)ErYchJXp zb<-Tp?<`~-8bm%l?p;TVkmju(N-5ri={?GGOqLy@w5w64j!XEg7bLhgqE>X}-DOZ* z0O;)JD^u>xI38G!2riJQm7ciNTcM|P0n5_VoBq9>CrnFHqT#M7B#ofHo_7ZvRL-CU zd)QPeZ+GgWl9E4wLet~NipCf$T<lc_6Oau|Kw}I3!>v?Gf_vib$x)F~+Mj|pc+h?w}GR)f(qdSW$n@?S87cO%F zb&T|gHnb=W{(EtFSW1H&T4KMUpH_gFarsW;>bXR@sOqZXNT0WX06{_sf6;7qys^wU z!LB$8zYh@>%l~kd={n*>JF{s}p>mKSK90df@GGhzWZ+T9e&<($bIidPqh7^+3NiBW z6|{X<73E?0GA1mE>musmdZi>^7u%syrY@TM8hHivlQjKq>_0acT!KaC-0g#nS6O~7 z58h==5I6MZ@T*;9w7FP$Rm)fiJnl*Av#{5v$*wERl!fZcY2lR7Pbd_NY1u&%$1lns+SH&JL}=sb@&wim4c5BvZtL#R z`@(I~K0kJfY(0#%PoQ~YA5J^98HPb zjaPw#yC}6?JA!2(S{0eH_+vgDMl}30L>PM`ED)P@ehg^Pkd>12rvFdG!L?Pz7s^bH zJO8WlmIh<&Tc4&tWdFHPd)UAVPMXY%vx|6x zS4Tha2Sl20t1^|E{~(9MxrNd};4LKzd_T7T%^AA%%r)ZAyc0{!S?0};b$!CIEUf?` zZD|CS;}*#$ks&kr=i%Yp+$Hg`N;L9#HJ=qaNP9MVyHfLZ7$d^tsI0@N4nZ`)#K?)*npsdeihaK>qo<@Ek% zX8rO%?nU$UXB60d%)4|dXsHTsiA_NYd`&MI zsjza0{i2U;@Q*%e@Z+#pbsxtM;To}n-=0*3X8VGFiC02yb;HU-=>UQ!cvIiSE@1p& zG8Vcx?1w?J8)T7{Igg8_Zgn|P@+5({YrU2ewWG(V>FJtoJ0z4QJN$iO?xXPY_QcBG-v4BT4MCBfm?^~knCXjdM*9mVPWNl zBNd@w%sWsaf6w=p8vCNh`=c3x$KySGBob9nb{gyjMt#uU6GYEOk&A^!p!*-scW-of zy51z*Z05qp^`E~QkSe{tyZ}>8pQ1_uA4mLjpJdHuFnT~%*ThsXsmF2&J|>ol8c@4x zcwnPv$~k!nD1!+`ZmDcVrt`Y{1I;bdbg$c*MVwVqKD`0}5AKbXd-a*x<*^BV&tIkl z4ZSYN(0OW^eL}~*Y|a;(jj>Jpi&oVh!u?WVZL#!?l^=so9gA2q*-r5holCv|pWPDa z;Kx~Gou8eP4oqp&Zj4UrTX$O9YQ&JEummY$P^bzjt{{-e%ZbwKNS}$)$DhX3M82@{ zwrpEyIq~H8{*8K=G96=YIT6&+*c(Y&cb3x^`MkjqTxvq?gakzn0hCXy>!@MA8YV6x zqCHlv30{Je1xJin3;w;lIIuR8!(&ejs%GgSJ%q1?*k2? z=>4$7azNRy)?8nA$aJS+F!cK;+edhbFStIh!5qS)G_yFS4DA06X>(6ly@qBubOt zl@A9Yax8)Jrm*JADn(NgIn#pFr24>tk3XjW6B+6CqGE{f9?rf!?5PJ0QGUF6jGG}6-{lRcY5dVR_}=f3DySV+3{W7AOdx-65mLv&_;5(20UO$>YEK{?zpYCBFh|7n;}pquT5^xpjvpP2 zCA!EG{&@ISU(yg$(u$?0KJFatIvg#UT0El#DZ$+nfnD@v$*Z*xzp)lnd2}$+B=P3# zKEN$6-`XwY{<(Tj^*8}zNe8a`V=%3 z2(dlawIY|`OV5*CuV6TBGLx3MRm>ha%+8AGNGKYzV#NVk)3%gCSUMVqvh@=v`+>>|_>BD(q49$IpBX zhm_>WAFw9rxnzt~B1C$$A&DEx?(KfN>rd%KwsN1TmP7>Ae8o)j=aLA#{2{|m#ZH_8 z2V#bqpWW|mm0wU0Xs>X)@T`1+jm(K95oQ!liPQI&FyXr*U6YO!V^(PQZ?sHVasW>Y&#p&*4TLzAq-^#bgRgR_l zxAERLBFS+Qte-h*U7wUs-Id_?j-ZAK5?@`6*jS$ogFZ z>FVr&k+QgVPosR&slZ4xL}l$e-~eVRN7O8y(F-6P2(DFqHkjJeh;8s9afk<6MDVSzzZjBTLaG#)u08Rpz=c#@MzE3^lRRGT z09n?v)M^&cS~jpxPrPQljiW?U_Y-(tzD6kxMP08qyzay0&H)4cHVV$*7OElwoRE@j z;vsjy-in9j?vN>KZ{k#%iL?M?^uJHv&5ybnx6_8;vTh+5@Lxxej}O8wp33GR25DPQ z#pkpox6{4gX*{r7)cy=p{UOeFzE?}`iOgo+_R2&+GL!h+5>P!I{5=A_J$=a%mt}Z> zo`=!nTFSS~4hJiAWJQ5< zNv=zQf#f>%!%JyBBeOp#F%eP@)|J~l{uJF&hQq!$;Bw<9ajA?^*+d(B^;@#eks0I= zzT27M{W?3=DTOJWlQ*DX^4&WDXWk9W(_ODagVc8h)v!hGynaG10I*uLA@B(ycu9x% zJM4!gJ~#W2s%y%hAg!qDopXqlwCaGF`!>73MjaIOkMvgPg4n&B5x|B48^uv7Gg~B; z)`VmD{Aj~-Mf4u;@_zBg*f(nJqTWUn8Wgd zQ<{rO7iI&B+2`6xCTOsP7zeqj6q2__Fjq%Y zF3OM!f^sb041c*cIQ)9xmu?6m`=V>A4tmS3vBpEgfLTkU}F` z>XiuXfUU2s!QY3@NZ^DX3*jy4Hol#67nyJ@)v=hCosn{OunIez9~#g4PiI-$h|>Gk z@j*!HH9VAIID^bO`{Vp z`1sq&_PI(PTusv%XZ2ic?6o`KKY-Xa$i`i&5~TRTdqS0Tx&I?%3+SYtA;p9ey)`)Q zBHm|y`);D%zTe8RX!IuLB;v((ipDX67HrZp}aXcCC_}YUtR+VL0 zMo7Rxh?$n5pQgj#dN1Oi3L0#4ygrAlm#;h(zy^fI^+VBsqnlql6nXPR2v~wI2X3!_ z*%Z4kgQscy*YAr%$J0(LZ&0gj=gu zixk%sYVV*$hIyO&iDSYeu5N{GULi4Bn3Otu!V|b%SEOM4{^LT)nSZDIORZa#AD2X%`l4)kK-5$Z|ZA07mZMGK$8Tdx8nejbla=09)uK_U=#X7`}Z!-Nm zNtA+#J49>qm*T(UlnyoQtqJZzzjX2={x&A)(VFzFl!ZiW{%~}?A_7Xd{fmK{*KUK2 zLp4CAPV^Che}{2+!W-4TkYTZ6pw{<{FX-TAB4&Wob-+0n&54Ha2J6-z*Xxlr^bDX2 z-y*Hv;1tl*x^#klrD{zW-F zY2;ZB&S%l1Zp-K-33gg#f=4XzU;fih)=O@-T0IGZl1p}(k0T;+l?tTo%2dUmlTW~) zbsP;^F3!EG5gDR0Elav)Q^j%@bk8k{w{1*dbzoINbu~4OCX^SoNMAIr zBiNite!T7}x2IY30`|>u|wV1(;{{HqW`-r2CAR zgDt$2tB)ZqdTg5~Gj3!q&4_d?vYt0i0T`Y>{0MEtF{(`_^Jh_3B&2r$jQ2!atZ61F z>W7YdRv`0iI=)YezvzCtsiebI3o z-QLpQhTg(=Qie3uD38_YA86r|f4;XgmF)OBE_RKHJPPv1DrR=kO)4NxIR^D(WWw9%du&I$g!d^ra%j@QC8oRO7#tgPcTHNSHB;Rq?61G}g zYhO*s~1aj+dk4V6QdsX&S5{FRNrH9N<{qw+f~_6+gqF1`P%iqkz+O z0fL@|j(@1TP3ysph*{ZSsnN5azVFoSKSuPL6NS=aWRN&fg;?0}Y^x0%r?PnfxS{gV zvko#Ee&`(0G_e-D&JBk!=3%uq+yyfhIpsQGF3I|p!LdM^1>ZJFO!S$qs1z@Q1|H)O z(LV52zl^$#6{@7*dSZ`>HD{KG)oB*_yNzkL`({h8r=@8h`vI~vhGA7BT zZDUf^a+zoQT+2lw1SmbP>;{C$x<*12D*IJx)`~tiCisy7v3$)3#my*B&qF}^PRjQO z6a5NI_%D>SSMjjkDI+j8XgFso9NQ9in~}kKeeXX{E-F4SJ$(Vj!`$5S((y7H#i?&% zWl4RxR40JjTP8oZ0?kv}CPC+9!@k<+6)raggO0aCmD;CXWQFU%4>PKR+`BXfK0L>o zndM#9LCAtmp+P9IQqkn4tLhMXr9BkBE}6HgF7qZ=T&!4!Z+TdDs6o?kx4F;Z3Gn%- zMH?cwnFf|q8}vUj+_lI4LXM~Rl0J*l+=;`nPtt4Zo559ZV* zOS-H8wsQV-#bep!c)$&@?jkTN(y;Y!{m>;*p36`RevO2Vdo&BYTdo#~o}rMhMuWin zVyi+A%e*%K*gu>g2#pvG+`e5u^T${~yQZ_(ruP^}*mpp) z_%D1gxYWMEZBfT=J(sq*d57I6j=LeQ^DS+JwN_w(Yw`8+I)mb_@D9cdnxumt{dK(c zuy|_pE9thqh94xfTC$&yp?hP+NA+80-ifRZ4ohVA0RTbG2kCk}pGF2!LcqRZ+6;qU zxH{KRps$r|=L53fWIn`5F8g=*6)q_S!eg*&li`H!gnjQ2GypDy@w&5TNh59%Z@qX{ zxSv=#62$0xtXwM+)oMU~Yq?MsPOe#~$@9)szRAO{x1;=?RC+gWR!LC@k~uS+lTPDR z$F9#-@z;dg(V<&5pRJNYj(1a#TR90nf?wZ{dC0uF`SE$Wx!^8muyj;c_m>-psBka# zi75?(^{>&tkRB!i(6n6zkFy0GGQZxDe3Zi~>}X6vGAf;v{hX)8VcD+Y4~fPzJ+>Qr z#Jzx5$XXj`<(y_ptA}Q7jS{a8MuloN(!!C9X5S4^Rv{#9qe}@h_O|Kk6T@l$7X5>5 zg?+@t5Pwn_vRr0E2BSzb##UmiJMWFe&X#;GlB^t=bVy-ocjESBggf5Fcp1)tw-Mut zHdDgFF&vfpJ;Q-%L|~bt&{cdi;e_f>k;hNe#X1$fNUD}#=1>qJMmCfry2@cs2*~c< zO`}2w2Ug!RtpAIo4lOTf3!9!mNCzISD@-qZ-Fz@dpQf!#MoVs0S57s%h^sG9%0T?# zr=A&NyOaa-7x~iA(ok3rfAQ&~YERx^Aoj%|-av1CR)nkNF7u7NNLD6es>3_QE4(wR zCacL=U-Fu?**bVUo8vr@dZR(BtVP9@|5(=8)jJrR(j5Eo&IjKb)H}K13pS+!Q(*Q2 zxa$Ju;u3&a3y?|9TaiV_UIoLR4A{}`6e)B4t4xE6H&=J z{|V|QTv--%g4aArk`{Nl2 zb|D5iNW1lQzDefKvBC*`ty95aj%`cc{-k(aY!@p?T++ep(AN796H2TBng0q4zw8r*b&-+L^;IcE^Q}uMTb4)AUCRQeAbLqGwvY`9JWue{ z-WSF?-_El|F9L4T`uVuA9ege7afK%Z0p6d>xfA=zNNM+qX>NO)0|}J1a<91Yg54!M zN~2RmBv^(R=YqysRX>xDWV6$v6vaz=OLVQ@-?#@{(%#)qsvqRUjB={Q-gmxQy@yM! zHDJ_Gru9(i@mrpWSeNT8ebvk7%N$|QG=I-ahjCT`E{?Ou7uV(nlS*6~)42R0fxz;K z{KRc_m=y*i38WJHPN#<2)s%U)%v{0P6Cr$|&`~c_XVqx+dpV}fzUV~Idzh#G~&`b*>v^Wb}_w)J@aF)-BF^pxFVyf0Lks3V~rMoOMF&EI|W)y70~ zOi-9gp}|81G22{Go>x|j%A>I(tZv3GQsncr2)3laXJxpEeU$?&sK40x273x*eJe_< z*JeF%1qeN?{T}kVl=jIdt7{b|A)URY@V!DhzT|5Bw@xrzkbAA=cko47vr?9SBXA^@ zb%K|xin?CdRYY~0`YS&2y@+sfverMLR>Q$g)`@@wEI4vw)20oy={^l+afoCmPrL`> zL%mmu4%0~zP6AK8UsSy`+D(q=N|2>`gfeGW#RszTTU4C?CtkM2jmn-#j#`nF3Iem` zCnZEl4-)+nCz@FHSl_T#50#Vk;*_Gs!G7H>rpt0XFMGp=&#wVAKn?$MjM|nS=`DKL zrQx2l^I35SYh9FS8E0%Q^jKkS46(;*Dh7`UmYwdV6FF58_GhED;HXqvv+b#n1H<-0 zZmi+amNG~9$>Rngu1p|5QZ~X!yd{XT{hK0UPGAP_1~1zFxO2e5>n_}6(nJgJp>P|P zp0~@ss7Z#8a%L=7yvMsO_Upyp$Sf#aE2SVMi5<%7vEWqnv_O52`P69m26IAssgEW( z0@-s}>t`SDsJ!g-Cz7WN3}(OUb!c$ld<{+0Y0QL?tbb*=8pYif_v&pli|hjFbDsdp zdZcssJ%i()jRaQT7c92o_#ufex)SD7-cw$@K42}#K3Xsto~5kbJ0Fuol`^_4MYa5J z|ESis3FT1z9gb&(Djf}}EXa5q)F)1PP5Pd?8x@zM8LwrVQMtkr8+~q7Kxj+!dNQTY z7YzhP7cE3B6Xf8 zexM%=VJ#qU2%)-I-zpfB+^CIevg=P*ppt(u86<(jV4f$B^KNd7ZJ1E^PVtWn6SLM3btE)PL2w`HNP;u3{06LUNi6(9a z5x(pSv2y_))-2geRHXQKn)us)KvkI&06tXAZLJ+T{DK>g_Bw3ho+~|&sZL94$jBZ8 zr|Y~0aAk^pm*ES92zMMQzbl$oBWQiS_JSE~C!m#E_%ch!-{kav1*@bPUT7oG($n(y zQQjVa)_Xxismsc%`3a!x+Zl?cMAJ!5*#Un96PnzHKF@bX_os2O??*!O<{tB0i^+vF z12+7iWcYe0KA-Z%Fx{JmZMP#-?{fm~Uj15efBO%1mLIA=YHtCTN(D^rzO^uO3Hmo(kCA?_W<>_5`pL~}tHcnEGk|?PPKPHQFuC(cPh5_6! zokghhdI_s?EKP%HcMH?(tq{!zux#4RIgazq$Td@o`^*)=l02vkV zw)rk!@(+U%+5cs|O3Z%yi;|8}C-aAIzuhk<4k)$-{U0&^s|M#y>3;q z@t~HfQ>q3;;0OagWR~AgH;EDd9i=Dlzc)WWiDC^KmP|sol7Pq@>$6Bp+sxlE_PNX1 zbi-;>EyV;k$vJ&CavYOKEf%%!?DydEs&Fp%?l|?@!7_Fe zIz^!DgFr6Rc5{vxiKQ|uhmmYoSv;bK2r8$Lc}VAg%XHBc&oS*U7Lc)}o{+h5#PZ{$I^+njKX!HOh(U1{BZx4!S;sWZM{e-xtsoia9rsannSX!Gja;w;uUkNtb^wty=&;(Id|yacQ+PM>z%epkd3j)5{%!<6=^h)IeyT z4HDd3$AGAC50X>!*bB65>WEUBsviz9_+omx8AtuaQSy}9s{!X&ZX-0<#D6qSBQ1P_ z9Lv>qjxlMOh>1!rzH&0Tv`{C444W@_$NDiWKlx-=bPA=+*hHY?sqkN5M>oh*5dibMyI_N3NZ zVS|5j=ZiW4q{VApFYh-aJxi+N7*I9$ zjzGM?V zVVl#QimVBK_3;`c{loE}0n1*6sU<}Yd+c_3+$RVCVVHs$-{K7+Kx)K|C-2C9sPD6`r)kXH&6Fgp zPnjXO8u>XMKZFFNXM-a`dP8Fm*e4y@b8_8?W8DeLaDvYFavRtjOZP<#@Yzio8ic_& z*D+}?e!ovf=p&V|9l!RFI$_@ONde9$KrM_efruz80OU<_%e4e$0{ap01ehke zQ8XAXnJU>XV1?=OJ7TRz$mUa;SU*#ztN$vY(17><8&`q^ut^QW__h+ zJ_lD79bc7WRYjB(MxJqxH#jh@BUG;!dsKdb6^TK6k#T-B%@HS2CBDGwBHPfKV`QVn z4!;Dq6ew}g(+KZRKtcC@k(&UY=?{ZrP&g^YIlFz{S(ntj!bAL_EwEU9`C0Aqi)1GG zPpiO zlxSWq<-UMN5Qmgv>rx_`0n36ua6Iu^XUKPW+u2DQVLKA zf=z(|OU?(W&aXiOX&QYk^nMY_oI$yrcvPQ+28#6knWIf5Tqp}B_yP~ zrMsj{x)062&VQvBJUnpNd#yRg9CN(77?2ckHZh@t?zTSfX0jDxBE&5`X(DtNystJW z{vP!4HUcF@l7;c!8L00Hv!O)zKohIPGhn`QEhg~D`f?wPGao*OEHew<&0V_py?4$a zOvw%G_SsD8AHGJte}_5SV6z8Gq~ZaTHn0bZ-f|Sd^3F8GJ8eAv`Hg+o9~+|Y9z7wR z7mYtS@&G3)G%x8>pMJVaFpiOJVEigo9IN3mxCYWPw2J}{;(BWwR|nm{Z7miUNqoRR zMo!s!!au^AOC8G}YmHkj@^G~W$eLqAk)zrvIP> z2Un^|KP?iV58{Y6+;mEr+SvTE!tvMI#vWiF5}lNFpg-2a9XHJg#=t;=svVDPuNlU= zpiDT2KldK~XFCL-MD%KmQZzD0%JtRYDQp}Vj16eRjEm|Gp)p?V8QH`(*CXib2fwSH z<8bs;t;*PZhZ9d0SRgD&N9mof|E?Xm`3^VEaSRr5v7-QT6T~#xEPU{H;8+5re+Nz} zC3?S7!5aSDb&wct5aNL4b_MWE7b0PfA8OS&_fi4#rebZepR+`mP`8l~?~(K`a%OC? z|6KXnN21xcRY&4W$^N>vH2?65BUIyS<4tR8zBt7DN4J<>i)S&c)-Yh){@rk1NWdDc zh|SQIj1|1Ea@1HHbW%L_I6qGr`ZIdJ^&ONee`5?D-T1eD5}ED8-J6G+)qs?(-`jg; zt9kr*w;7p7Ti=RC;rST{=lCBlkMyQ!E5;7H8$SBA#RhSj(`WS&3mgmSB8*<1tgdP! z3~x95`1-*5`jMSw6Wia6G*TiL z^K2=OWecPCv9?Q-Ey3LBw!a4H%t8IT19sp!a{xj|dTHl=YrkN&7w9UfzfUq@E22CT zb>AWeF%DcJBm25{+bx#ONaB&dIStSM&d?1vK4D+q7Ji52xcu` znv6cHYEQJ~R?;b?87Fppt^sAwPHUeZXM2%IR@i}ON#WO_DTlqKstRfRQO-Jwu5_gN zjjQ5q%~$(hFo?Ms99I9svf8nTkw~!F`UFFn)l#U&+Kgq^8yM@20j!&$=O@0~ua-u7 z9Il|?oeG-6!O#M0z-m|?Yo-(!F#LGT*18Cotn*QRXQ15RLUP~`!#?Chnjv-&>P_7fhu4cX7PTl`GTo}gDcd7qXoN!7~@qasQmvD zICbrPR1KTx?Tje2M5;Nj;Gtn9FTX0g##tDK#w;OKb0@S+V z9%7qiLSl?#6WG=xKPV3tdss6`uuq)4iut}X5Nn;bkqYtQ{1yQiw3fLf+pt|uB@{3^ z`Nr({Vf_yb!En5AvMw_E=nFKTH?aEs-lrPA5T$vZ6Tc;fjYWCd55(wjz`~P>M$)iH4Tq3)*A#@H&av%m1g^lPQ>QvPc-ThyEGrC0{YjHM@#Xy<3b;F_#V z9{RZc5F*3;(q|b2vv!7XjH>$#1JU$ss)$ZGE?*}2-43-~ zz%I3bLnSt(1ZI&NADeh`1~k`qRHb3uO( z3)zJ={pZoXSm>xQpgJC-HuqX~k5o{oP#@+TCG;gkh-0IXR}y>i!`pSlxn21+qDK0& zj7)mtE^*QDoe<9M+k8&(C-7`#qJ$XB)*>g(fOPD|2=d+*si^V4^~`q7Qy=q@e9zuf zN||+z2=S8Qh-X@S%;$f}30((nLWV}szaXY~RHRaCnvr7;?a1GDqhP`fWqjF163aWg zY+gqGQ0yA{9>v5{;_f5wI-h5 zb!>m@P-uH<+9M5de2#S4V|v*SImWtA?6DzFE5nxe1pu#F)*&bT`CXKox7~2i`Mtc? z{$~Cu0!Djy>!xTEgZjHi+X~%zWS9~Yz7~cP!|C{sk*`U`1`-do0JZ8X-@<8T(6TcO z^!+D-Z65)Nu-oT&8aG!v)zWsrNWOafbonpn)c>1!5(2^8(k?ei7T%zLap|pP5bFCZ zYZubc@)JL_86cHx61x*fYqokZ(3LeNZ$^ihD-X{{=ZIrtd>X+O<82NuB({MW9mRYO z#w)mitZ%&RjF054^$Z?M*`YwF0s_G~MnOad0I^(v!=(N@w)c=wP2c^Fa zaG)}OOVXkIx0@|{>?xua#gGJ4pC#DXs6wUvyDGb|hz;R?!=P+Z*6_+Sy_x3Q+Mxdk zZn^2^;_I|qk%Tw1#qKIXR{3V(xu@&<1#cGtd=IUHXM&i+yul&yYtVqme(`)L$?o58 zjzXgjOaJOI>R5Fu5GbX*#nzL9PRqyfYE>wlF|jTf3c@=PYO~j3A_(1+K~KnM#jR?% z*vRmZ<*KK$N7ynM_jUs%RX1)Ks2fLB9h;%ww}jo9j!M>*Cq)qiLaEGYeaP|S)fd@D>m zNnw%67t$tdV!{>XF{HcMa`^I&4qK+B{%{180w}1^y1?c$5xNZe`WLFg6vh#E9SGcP zi1DPy@6ac1IKE4wT$hMp6U(>R&rb(imd)!o0s^Yf(d?e4u3veDc z+8U#0#ZE#Ffm+|i4_<(K;<$n{lKuo(?RkXh^ElT@lLXzsVd`df1}+t)rf|i>JNtSJ zKAmQnP@7Oo(!Tj?dyxG4ms@)7AZE;koZuR}TaHuf!%Yl_!ON?p#2>(`wP~$Z{ZlvG z-mrr{mG@ajS{zX>lj0ae(B$zFj>7w-b|tM}WSzu+MG3SAowx=ocTeZFJS(oEQ*hN_ z4Sh-c`-**z*HpWunvDx2ICl)kH^tvmW=(=c&;nrhwO@~eO72otG^;`hc4!NTF(_v=^bNvvJ0DRyvy=5r zh?$NDqif7VFGfk(1ANR+hyd^wUUPD^K4JMM1-D% ztRsCE$%^AyrK}gx(KQM@jT zAn7fm9U<**gFRZ8Yge$Pb8bkFq{T>*af{~W*C4DKnYdC#c0pTl2CJr!psb4^Z)|fC zpN9*NUTGLc`ChLU{;2mW$XFs=sTaN;=S0WRthQ{4&B(PCseE)4T;Ay*p8dVyYLdfP z#Yc+}?0@2}BHPJo%LSZlajmFyFSp*8UrE(#P>iuRzU_}AKOy#%Xq5E@(|<3SaJTh8 zfMNF;t4eXmU`(8PwI{p&vyZe3CE{^KQTm#I^eHi?sg$IE$mzop*t$AD7DQPEwe9dU zy0d;|{i3y}Z!OS!K23_TZ7*2lw07)tn&i$>EM6bXRj!e>0;~I5r#Ac+fN|Xwq=!@6 z@)PNP#RY=^lK-wsn4N&5JfAm0I_*D76 z)f#_*K`=a*3Lpeg(7FK5zME)!e}GYR8r70tZ$b~a`N93}pyOMwqH*-2x z79k)}*dxsuR~oi1o4(h+2ujC9xhu@g*3*uP>pPhi7!yLzgKcWKyh8JjOON`gEE&tM zKAhJhT(4*mVyS}9W%Rn|_mRmGF2Fe_;H+4Z5AdKX;+^$`7X1WyuI4aautfMJwwphQ z)%yl3+PDAE)h6PT78FtzGz0i>g&W`%9j;42VAQ+ReQA7&d9LrjqF8=~+ia21v$J{{ zUqxdd1saUIS>1y#f}o$0L32sb=PT$F6Q>;v+EUaQXmf7*qld9y)Nu>! zqkcS7%mf-Ja9;(vLME0^9^4l3qyIL2W*%6GeXSlhEmd&c3|_$zSpTlNY7BJsSbX8$ zwY2JfxdfRe31(XYpFTFrG|=OYmxC>U z-g2HqU0lq^M7p8uZ8u$oD3KDn84Yd4_@mpf#|}#TPrHj-%8K&w-P@P98MR9CCS;ub zq%K>nGRL1MMQH6fCtf6s%Umx7>n|zzf5o(G`Hfd~Xj^ z0b>-Sq`VYWPp9E4?5w>WH_4wJ>xSkl84B_WUnUwLa*w>)O*xbKTleCe`q38reG+N! z@KmZq+&LG7s*oP#RHV*d^O?2{YSIY&x7Hc*7AN(C5=z1=I-D&lS=%22|Gi{x#BFTj zu>Yo==r3X?qC_cmzkacLQa5KoH+)c- z?dEWpfx@B(rRAAf*H#QEN-60K03mMYYR<^Lvby6G92RNd|Lyj5TE$sC4%C;%`5{y$ zg&e8qz3Ni7k!^J40O1vu)ytBumNBPenX5Dk zkOqg=a-mm@mNfov`)`2}qQN))t&^#^K{ZH!9nlB* ziRNG-fu}CyVs5BQ82;WOXM1k)qc}Po?-9>%BgVxK>W_0n;vxLvtOuAO0`kjUV*DG{ ze6VK!xM7MdNSVuKZ~S|O(kv|V*3irw1b-NIrfp>=Xtm=5xObY%yom}cnsgIPX4H~P zA1erjZ-h0vFgkH_y<|htntpGdUd>$7IkeK4Gg4e~_lMq3oIKR{eqXPhnxh=LzWY~L zfj~u4$}T!We7QqxQ@$Rpq1*2FsIMaDS&gP5*pSVj9~BTsh_=!MP zyv%*L4SbL)nFLq=PB$UT_myxyPCZWT0UXryn&iZAhmQiZ0A;mzemkQ^X2xJAT|L#%^{f0h>}tX;sc8yGpX_WP)CP7eD&yRFEZHoy0ff ztJwE#2A1eARKn0-&ScPK|7$>h36hiTdxGV2fmE%HdKIhW7dhRVnKtJ^=xmNi#gzci z2|tnT2eVEaB-Yaqqgsjm*$5WgscFTjQuU6LrVH@E)|LNwn zonq&i3iMHzt-VY~C!`8X1_ z^eA|n3cUM;vX>Yw9TAb;&A%oxwdTno=x4*%WSyIRF8kw$ybryDc+Q|fCx4Y6d6Y9y)AKS1+4oYd9e`av86 zLPGncUm)df@$Hn>VeI^9!4k4TyK~T_aX`dPBmJh%F@<4o&Cf3kTf*+VF@F9libEIQzz*eYt%RKBE z`|Y6}=ZV)IdfE!E7D4v)+6`K=@dCu?t|zMb8N5--C@h$scQN~E{lx@FNkatmiFe7? zOw-8s^KP|2=qQ^Q;8hc82>2H0?-DFuo`0fV(Gr~Xk)rS4mR2#OHuC$4xGRHT@?R&< z@YL(w&}_sz4Ep-ws!@2~I>QH*DnjhK$F|M4vhUG&*cvRPJJrbGvU>yHQR1fc)+skw zbVd!VS?99J0QPFuyx}m(%C0^;G87v`6ODKEa`im|d)@(rxY_M!|5$75j{aRZ=NX7i z6mYl$yXT#SznL`1LtMs8F``nI1$E_Xk@H-F1Q0@gM)NLMa#QL;P@#kWte4K}KclZw zygCCbtnUmSuXQqt3T1Oy4I|vvWX19Ln^R+f4MyJU66=A_9|Cpn z(7wOH@c2i)1uGgxZBo93-vFRn6Sq*|q$|a=8$jenL~PBIa~O;15$EX!j1M%POR!0B z!J9J&LtPoxW=(NI{PNi!(`enjSg8paxLd&ht2z9?XZQ5#4tQxx3ku^TSy5DQ^# z%RSw{xz!w;ar|Nztl+jm6Jkk@&0zRuL0!YMVhzx7-BzYk3RJBePW@$EQ;jjFC-Ts-ZPzXhi+JYFn$`zB(e zLody@xDZ+&R{Pe2#(N#;7P^E_cHD1~S+u2E>&h6F_f2r3+b+9=cR4Hi#C5TQb$ZSu z_{siSsV+N;hU*zC=t`v@P*)h+GFD#FIAY|U#P5_5>2pa{g(UD(W+J~qRAvr3sF=*W z-p+kyyi~lL1VIEEsW!DZYdUA3h75g_vA-X3@j;y^V90s@CY)z+qKC!9F&L)I=-GdQ zVg0bPkm=U(1tkkgI_@24m)L6U1gJwS*_9J=>W)%QV_?KlA>ge+l5nA3b750MB!G+R zdnWl?)1=)wteJK}nMUq&+R4^`4Xhoz&Yxk~^rJO7&zn}!yC*P*hqJ@ndu$qF>is&! z{UqJ+`4}`a>j`PX5kYgqC8z$^iggq|_waQq=*?eCYN~KFb**TB+f~3pK2PHAM1?tT zxTBaQ7N_sce{9}9AJsyeKm*y>DVX8ClkZL%NmoJXVKoZC-h9Vp!hA4F`*&}4Czt2dmKZQGn8y2<6Io4I}RfEQ;`FSb~r5Ru{#h4(@ zf5EOnUqxZy8Nni9ba250oQSaUrMFaf3uyj+Xjb|5+?%e6lg~0U^n;}gV=})R6RwW~ z*ji)XRpD~RoX9_QZh;(dm(LL|F^H!pLo)+yLQQwXMe&+Gx8vmD<*M_i1oJH<(Dju? zr&yphY3RKG83y2(!0Etq0p*PS8;^g5sbB9HN=djD3GKXxP$(A>5+7o@VUK?ctWAx3 zP~aN*NQ|@d9wvX^`%^6YM}U zL-0?`|DXGxSSAmkT5s|Ms_S2xRz&ngw}8PPC&eqDlu=YLg)qo}#UL(tW=n#0lY30` zxdqQ{v0G07V}#p60`ZlLN|LM(XxRAj++Y)}QOV4`FCa?1-lX6DXYQ$$$LncRg=$5# zB;17{Ew@%k+Q66*h9v{&MqC)v11?7Viuh0T<4~3+TCOYG?n?g%8Xft0%|FT0XKkt0 z!7{czPu88{vU-AKRNt`}fCWjCO#Ad=p|u zRpsT}YPU*EDFBCi%p8pRZ=H?=HyfF`48-3SHAkRLFq}GC6p{sp=E-`zT%XD9r3Fuf zyzwuu9vs<*Amdd(J!d~DA(6gucTho+ty$eP*dgSxKY=;lj?wd7>K}I&r$(>SEey47 zmbz(GV4LDZY4pHzhseo>6d$6WpZlW?&ce4WoMAhBJS{K!Ituf@QiU+gzDLXErdYms z1Vuv85f2rwb=FDNst#E6)PH)g)TO4v>MG7GsH&W%&W-Tdvk^L;;Gy!dUK*jx*fk9Q zD$9TTN3vyBq<#ditrO#Gm}!|-E8z%S*&`8d$O4Z2Z(vK|--JIwVj518t;LB-K?T^- zW9FvcwY(t~Nvi~vmAJ0eb{MepOfL1JDguY?REZR1J_Qyv$YDmM!k)9Gb0_MCjoO)g zvh}>S_%}>VH^IN%@(HagX!S)=pjt-0b?^VU12f##48I&a|3)JnY+<`Xjg%QYw0k|b z=YKluC;YlDLJ%xUHtO;O7@GV*B`Lj2ER_k0aSv)KdT}!7_Bz`#`!PmW$^fO-566r> z8Yz0&@I7wlX_Mr2X_fa5?qvEN)9rwsyaU2kT|KW*P<_DEei%HQ`&|cJ@UkImlsjRD zk|3iA^O%2m%yR3~wn#7({rQ}D#USJ(bZ??t`X+of2=yAag-xdrcu&}Ygn;d0xjmxZ2h3M85yEyDX9Dvfw{u|_Bs(qnB{qE*O5xTW_K{v8zzx}z z#TGe8W2gTIQ_B2xL*HFn79_RCU`fUO1sp$n!^Gg{XpSK}c7gwXZM>7@zt^)pAZhDVya%-uFX$Ilia*jL znq)tG_uyLhy#tCIp?X?ekoYeEX~|Gi;-{Snegu~(C%BB8FG|Tla@qaJyY=6Uwk|*i zYTn?>fyL?!1q`pLSi?c1QnB6*ZNWmfgESecQ*> zu$J3?HX$_A(7OG*x7`*xq7Q{%OPDi*G;hlcq1C1h@A_*?$n z^--A{=)#kBC*l++uxnqODT6M08YuSrX!!m`zc;V06LC=%airL=vF1Gl3J&q^Xc2M9 zEF>1^2v09UwtiezfNXP_Pf`~d?_TI2d0qiIH-lic(PfudB4IAkD@;`ec|Ak@JA&1) zlQQv_M+}-zC82QS@u|^pQo`3Sld&Z1(YlOVa(u6Kcx+}_YJSB%_Q#3Vhf7!UZwRR^ zbhO_P=e-pM`r|Oa9e&lxFg4^GMK8a(5QU0NWpy9%j|jD&Cl-fz1ss9@MVTO)$DbXN zO9}4=tlrjtpj;F81{SI^5#PJy2SJE2giYTPveNc+XHy5ttqke9>ogYeX@8JjxwG=+ z5mla=Kv<{K7gMmp{%;eb_(hP-%ff}jg__N$kd%?X>gZ1F*eIpw@DqGj^~w&?%s+Y( z)!)DNSPOhdfjx~iFatIk?L%;THYFC(5kosBj8|GbMOM$ROBE?BwXiot$l8@zBde)y z>9!zlFC;?hF(@V}@ApWbL8?kxqOUC}#XSYBUB6SfjobkU>9J6iQ^SnH-GIH81yopZ zG>CcVJ7^2DKo~5OTL$Se(hxD)h2L?Id~%8idt+w& zQ`!2=cQ^~^vHGmKwF4|YA^5#5$3Yho-T7eL_TLp0CQ_yIO8Cv;HDFShRIA;AibT=0 zLrA6*({toZ&l`{U;}Q6pec(mYf>Awm;)}n2;J@$ngUQu&ME9V-AE64;7_&f{6O3YU zTJz8<*ZwXOOR9s7$Y#(q{V<$|F+(tdvcqFG>{CRO!5^KT9jcUkxqQF`2c3fjnzNXb z1N~>4I1P=MbeT)Q{n$1cs`T$yobZj>%tk9K?9&cPrPl~(kaZQikYyoZCisPd7~~_K zlBX_-j@T?RGG5)#=@)vBd>=fS zWfLPEQlP<18Gp(FtseZ22Jf$o@__x7RnI&YwVCnRYiC|IhWL{Z^U~b|C*ObM*TF~x z9aouO9Zkw9cPS6}k=0Sp{Nat89g{vC>iB$Y*ItHARTR4heZ!cz@y#X?t9=7P#e@tz zA^mGMGaK&DvA8IRbscnGdf#IN1&>yP z3MqUl%P{O-U!v&uTCGSnv&st+_&kCXJCvi8RaRfnI_1?Q2FM0D?Mt!Watrqo2WBvv zsSQHUZs$Mcc6|yS_%aY=xdHVlvQyQ;#4bI=`>4v8D;2sdTNiitH549#kcg|tkVI)q zxo2fq2NaDmnAZr~E?(bBilTt_BV7o4=^o80GGm`<53Cb-k{0hh`|k0{M%~|mMF0#E zSh(mw^6eUIqT+iN*w_s}*xtF%c+DM$8AmVx4yNmhkJ|>!F0{(x|ph zlcXg6?_ECesxN3GFTBHnv?Y$R!m}I`GR#vRQby}!GJPLbd<8*iggQQdazfr9I-p{D zuU!?1uqx{J;NhbGowHi;;U!ong|Jzp9y?&~#~&`6=@=VV$8UyI?HWPoPd&EUB&0Da z!(s#Px1;~#8eaa97kJyz$~DrJkG1n=r3_nS*~U^ivMF0y@0kCPe6IWwVri5+hB&tt z!?!}@o)ajvtd0r}s%f;GVu>v+Se74JPnMD~1d# ztp$@#lKJH6dVN5%Vz*2M=hQ3p>nsfgX?Pl*m472>@Vo=Owx$%+l&O@zCB^K*j^H(^ zi~q1UtieluEvoxLc^1aq4s)_W3+oEbI-xGvY`}!9jl_n9G<^l$?J&yb7S-~^faI`Z z+1G7AS^oBX;edF*W}cBh;5)EK)rA@^E2leobs`CXw_@=8ug)v@lRY^<#T@ z;(U&eyt$EFL>LvmmLg@2lJJCsPjWs3le2UeY~)z?qRy|lFK`|%mc8-Oaz~HKx}l-a61BZ66R#%rVB;fT~S6g zdDSpV@gMJBS2am8NeCB+7+gYXq`8Q1j0$Uh&v7mSwSb^Cl3C$uGUMI>wfzm09FkNl zRW%n72W#}>??}1OgO}&DS!z?1NRdmu%3~Yi%!Qvxe;>IA96{XleCWpn+bYwoy_y|+ zJ|jAHbm3|6sYjhEY_xUfAw~73EZ-l(ms}Q=yox4oRck1cKzrFSV#+mxD=QzY8<=~y z7AUCW;9d6hNgoO84J52cF~b}ZSoo&Yx4X|41$n?XoL&2dey(P04Q4CbQsL&Kql@RK z#zwJ5Vo|{9Tx5@{yI zb@7RVRWs-o^1z)b#ol_US`g9Gv-%TZKn}02q#cZ|6R@pJ=><+&E~v6H(>5czfo_18 z}*sG0Jh?^j6(Po-#C*H#bmTV&hs|DNP=k9Rt`0(^l?`_onB$ZpELlA>t#COfBNPh;ZMo=P3%G`JM`$~)G`apW z?JNIk%$5xvsfiDM=Sd(${XW$&I-L8~?&&WWLgoQ02FK){5b`hhlmasr(z*BIaEI#8I2|4E0< zo@^{mM&V2V*Poi>qx=3eqi&mzr@Eb^L;9Ofk^ETO$D-f8yTMfg0gJCLKX-#|_P{;G z1??!v>Ap1|zREKzAe7M+)nnI}^1`8>{OEb=vy0R!hXYi3*$L3H;{6NFmP?Y~SsC!X zCVxI7A9;GbEE44z!{^;G-W|;v`P}b4IgH#EWibi9KOP1NFG~}!P3OVlmDBlM%(-F2 zVm25!>cTx}YprqQqOC_LpZ`b(R>k1T?qOh+<=Hp`-%%8BiMPs)w{_HHHf(|-g8S?M zFb_ zQ;h=$MjluAwP+hq5IC-FS2u&3BNZ0JAG;nqp@;4L{`X2;XWz zjX`prc@oI*TGY>n8^ApF9-*soPxtN5&4*BNw69c7xArInz{d2p>G0Q|yxWUi5>s{l z&O_i>h0r2l<-z!LhyEo_+iyL!vwY46zo@(V^O^NU7tb2EQ;t(k{`Ca~gTQBNwoajf zO(2wLazBA3H6Q!IE)W@F46%|h8}$)5AE3sFKwi(j6kKq?CBB}@DvRHQg>|Vj`+$EY zz??zn+-r-d8I*n%^07En4^ixG93*BJcL$ZSpmDdT?Zy=BF(lM?h~GQDal`;|&b$$W zrs1D<_z?N$zP|q2gFn@5P{1*5LS7*m) z6JY&ZzIDK+MGpOkY}<+q*82G_{ZuOmskUq2)`wpl!!-dXW(i+<8KJjbt+RgY&-S$w zGUl96aHE7H4pv)E+Dh%6TxFIfHV}(|{RnEngj~)xj5)z)AXJ@xFD)yGX_=?2c-vQZh?W<)rl;(b^ckChcntDPY+WO(d(;O z%1iWj-DkHy&8LRzUu-9EFBQ@-ew+#Lh0h-H5H-^gmsA%jWUTA)j)t10N_x`Pzr1U+ zA*MDZ39@^6{c=0tsuNgo>{)nkNZT$zs3f=In`*1h<1bGA^>BX>eZHO<7Puxo%G-Dc zV4%4P)LRwR^{olMmXJ_)c7&#f^R5@HA^XfSrF<+RsJJi`@86r)R#n39a#~hrWzqO5$?U ztb~uEn;pB#n8Oc!cfH78-;yF5987t6zJU_SKAgkNVeNji*?{$>nxZppTBiouKP{b` z1}qkJpE$xk04QYP;DYuNLjWrdg!|GvH{vxJv|<}=u7Qqs22{` zfSKaCse{mnU2fa?!AEo#--apnH8a(9+(p8VUAX%{`d#UVfSaH+EgLjew9es6-(Ylm zEq*+f=|0N8Swv_x(y$-OcJUx@b3eP%aglfsZsGT$?7;3lts6hQIO`d?SF^kWa_QHD z$`@E7H@VfBf`FU5SWX^C;UAwAFKW^rp+Pye4EpMfd8QJ(?{*^XU=EpX!P*#qS&0K4 z$`|?w{P4cdLM$^&HSad$0>#$Wsb+95U(O&W@A2U&FCT*wmX_d`S2dOHuaEKtgM|42 zhTd{+65RV?8L;Wz%ap zw{^fw)i(hHVV|ay_0Y+LD@d1z@umevk?M#=Bxt64N3Cc`d{3a>cI~aAa`NjB8xqsh zyInF3f}(7%(goyE^zC2U9gQ-mulYok&#d#fN)btGl&~Z5H(_#db!9PPaf}!A__aDA zXFnStRp~QXRvAvB6aCB?5t8XOv=ah+&(3%7(>>aT-}B~rY?C1^VT~J18%K`;`zU%d zd4xh}ehzl}%2Eft@Mf!BLg zFtFn`#xbkD`*yPZ@cZd?hRtfMO|s6<5O@EbMW?dpNlg|X&_p9aiDUh@1`<>X$E7>~ zA(Ke$Ke5o*cey{X?3R(Ml+(Gb62GO&$6;)@_#aQ%s^|QZ7UmKO^0*l*?ckMEH8bn+VB)`b?ax4(=n)+SW9ew@>2w}wLdtUt>ai6bPILMNbvUvZ&#$e z*jTNLdDzISxJ`Kn z`7`H^purqj7UONCQBjxWN6a1gxoo5hl0Rhrudw*H;`Q;g`e;W>2agF`U+xi{f^l)$ zJ-j@BlrGH=9EfNY$9Omq~E2Wh5PDfga-=uw6G87xXP3w%#sLT%34;*jUC$7*pm!(B_yojC)=;vva6iBpJ` zisdufYr|zm3AuM2cQGE`ok2)DZSRdLS;lnkg=l`Pc`A;Po?{;Gf|gI&CSI_qK5LX$ z0TukUUM%e$*%07uEdwV(#KRN`Tybw4|4y2*7;<$W+H2a+UpJ+#7OKtqXN?oL)}}s) zvfj7Bq8xK6ZHVI@tb={eGTietOCgq+{}O-sxEDrxr`I&ye=r-O5qZ2MQ~s0~Kql;^ zE``78dBnyv?pg8AGX?@bK`t8!A_0k zNM3j%zFgNWffA!y!pl(T_i^)fPGIC;Ed>|9DJD)&&2d4RD0fjQfp_8% zg}pk7P_4!@2BeB3P(_xl2`b}FrUoOiLl6KCleH#XvOUpxUkXws9Y}=L*Ca(dNPhXX z{Ulk8LJs~s9jYA-4K2`s9n8;S0(#cJt0yKh?yLVt7bvgs-4eQmo*E$px&bOj`!GEg}g894P4 z05C7qu28;NbJe7!;b2gYD9&?EHpeqy*SRi$zV<*k#=Q_zK!f(wcmKZwhQKl2r}^#N z2*=I!I8lFyrNm5h(Gp+4^QKBR0ekzyue)yYC*{jKKvFFh_`IKdf4fN*nEC+RK_)xM zWD7H0U|Fk3vs_!{(hF!P$%Y)to^TFoUaV_{Ftgw9Y;vK+vkx;Nl|%45WQO}}X(#f& z+DR`&Kl}V)ZSdo#zd6uz^trj3>JB!mHC|~HwLmhw&;pAPr!{HR0)f0xy_V@efsen1 z`IfyA$j+AqYl7~}S62fsI{4pRw2%mU)e`eN7yNrpK-6cy6kXRnTyCuS*6ewC_99wi z?>2N*ROA){8)+M6$u`CCVY< z{JH?)BB>1x+)S;Dz`^|S0kPy1)SqP_NNRSM@u^rh+rVEHKCnY9{9eMg^f!f`!laVR ztPFAp#}*n!l+Sq8XOMUDGlqm2ZiInS%F+_Glh1CETT*p`f)mkxw*7X*K{w+5`L6Q$ zox+P5c*I5)I&Jt^V|MmLMnrgu)I&4mKQ`f0_#

}1-T+5E*10jpH@eRVxCHM)-L4Q>VU#(}jYIZ?pDzw4h z!x=6%peC(8k+#<64nlNqBm}4BQuplALDl~=o_=!mh0BDbLnl4PyNwpP!g~0R!=T}{ zCMy-`>7PpuPZjepXiC@jdL z2ZaIur^FH9`j!%}HS3$szGQjGxO%`IZ>AVm!cCUY#Ia4K`1I}~$4g2_nirH-C7MAJj(DXsYx=Nl%TnS1 z*Fx36gEUUsg%YW4J7!ybj&_zoT}E)Ns7cB+7@rXYtswWm{5IV6y>+KS6b1*~2R(|0 zj<`f%5RDW>@?%YS$Ac0Vp?su7lnSY&X1soNai`z>LFnf1sABn!v-nfz$3@PM?Z9m3 ze|2E=yr}Q;TF{Lf-3c3|PT5Rc%n4(Wzqf91Lz#4*9^c(%XIKR$NMG!Zv3n?;zk;!J zD5cWg2ek*D8L#IcO%XlhgOA$|$vz0WAJb8ugT{U94PsHIfh1f3tZ*jbvn}$!uQ9WW zu5V-V$ao%yzj4Kg1!xD}gzY+{FZcVJU-+wUW=e*r3B_HM>pp?DNFjyyOt_lh{;(f~ z#Urdke`8^(-QPb6@0YO=vox=1641Ak9|boMV-t?jZ7Nh?{!4*}({7Eq3Ij!2v}&`T z8e8G?;Ym8vCfUju17lmxJ$xvb^S|pMxD?CjLY}`$FyUNwM|sd?JV!)FG0tu_dZYB1 zFYKbRDmx_zZmDNFx3V8tBA@$S>|Ve!@u}#MY4|rUudA#*-N2otfxYqMAg0u=xJQU> zioF=~DoF5<2gt7C`R49$jZS|*&uzb3L=ZvWK!1~f%+G`o9zWhqN`PFdNO)zM(mgM} z*wDihC^eu;$$on4_rj>;JlMDo30*}VlCM0GKYymthW#wE@Gd?YW2!(tNtH2T0Sgy{ zaF`&R0{_8E3|l@l?1Q5{*iV;{Ryzur{;e@Yf>`=}%N~@wV=dze!#L zf9Z&?z1BtP5}~(A2}KX`nbVEDmF7W2&BwAy?Ox@m5Af|iN5K{N)41i!Fb=SfR~uR&=Dfq^d_8%jp;Nn0qA^4NsHuMk`>dO^tj%B??(e&-SR z9WMy2dcIUkky~c7-W(FQzi3{4R1yYmrG2n`WK-7}a-(G9k0AbsD@Hri0}_Z8gwSzI zjk(sCVL>L_0$O}3wV2L!E6645Tcud{jh=`v%dKEc83W%A*v6dyNE!i5I|s|=)Ui2kYw8s%t7{ht zP@KJ_=LTRZ2l225ykY|(ck`xU*7dhsy!S4Dm&V3X3$4oMG>sKJ+?F2KZza?g3&v@p ztjrH{+5-`g&9ezd(00%+ltW3V@&Hu;e2~H~qzhGmNuaYqUzsX=Pl)$^7ishvl|B>uU+C?x z`=OTgxBh2QMrkjbdR+W4&3-Fo34F_})yy4a-`v^h*mCLd;Xar_bXmB_Cp@QCd@0Li zFe9V6n7K!mfikPg5(xs?hwdu5Rg`5!4vm^%xjO5>%-C0A(((pfTNt`6H;Su zBmuKR`LNJC?;{Skt)i&|1%l5jZBgu+yat3iTF;X;b5asz7Wo354-^k*4FQ9Xr`}6 za@&mUZ)Q;SHpVZD_BkYdF>?}&IC;(< z3M$`>u){Bl$aOO1zW-ltt#{M|4BN(%Kn!gpar%pqQOdW&2+I!zQQ&cC(qa& zsK~XBfN-*Nd${YG$yeEEMpsqI(5B*&?}oYXc&0Dq8@rg%5N~Dx8uiJLG8Ln-48Ae- zWtG9BU6h_HSP0=h5jC@i2u^#`OlLGDL9|EBrky|7NnuiaOA_igz?^mS(k4GiNnlXh zJNL~P`j+`&H?XOjmg0u1NutbY0 z!z(^0nYCEK3od$O>5CN#@FpTacYZEq=dfttQ(oBqix7@iIlDv!K8m1tfq{0oAC=*~ z1^6*xuGD_}P*16|QdL70Ul{MIEL51Pcfbnybd@8hic0vK@}Ta~A9@*|qE>v2;|i z(+IE;=?z&=MW2BNZN&XfoTl(s%1yu=9uc#@Nf>94azSmXQ>A%?H`#?Snn&Z8fd>|2 zxb9X>c@Ft6?|pfplXS{rUm4Y66>dX&aVwpJ<;8Du5p*N&bCQG*L~xJGTuec?t@DTI zT##9PZ523AR_DD)L0(xYxb$UM5GM5Z8%HH-ncd)p`aNHZYih|HHhK4 zUlXWiKZk|Lcyzh6z~T+uk_)<(rwe>8jrd)iJVflzDKgLS7ubuwG(cS_u45X-mgPiwD#XtjW06eL zv(+kk%VUIbJjbH~+9YP$%p=Mkw9zRQbVoyc>HT^@E@+G>B*1AW{di8_9PYOI{}>q7{sk)2WfW`Qk6k9n2MM))4eZxQNacUono>9?c)V=%6== z42DLkSkmZxC`Og;IP+_giq$}SXCybV3Ck97bduN_v@P6*ZHXo_;0_AXa5&3UQC|o5w2n_O_6rg$%!Ad5sM2CX zJo|V!K9yy}fm<74k7B5>%bFBPRtHRULjcf0FDK2SujKA|o^B!k`@1iBgnH|>ASyym z$MD;G?z%0O z!^lL9q*eqkwALDGbsRMV5G?x_$%RFZ8LGUvpH%f^+36eIcS;N6o}@~hw?@1WtwGSA zGFxc4-h2@MWc#pZ5m(Bwl#&+tL6fjGL1#aK6R730!3HdJ;rkMCRDvZAX7J2Xu4lFYo_Qs|t%@Zse`10q_-1ubU_E#L8h;(H zOj)Nv)9ZMHZ0A6bZW51zm%C&2hR#{>{`q^Cw1u}>w|lb{29vgH?!a=QsW=7^XE`F$ z6S#{5d~I|Z@2kv;Rr{PZzdwiqiypBY6`#n%Pnk&G!$s>3Fe!@p62S4pSC$Q3-YOES zT%);A=m*l{FeiHZMR%iea1Zw_WO;>pUyKgyXL+{`*scd8=L02v3^EYB?fQIfo@dh(Syo7t& z!WPXG&c9X~n#}5?nK}GpKln=LhTKOZ?0;_a&`4}&=Ec>+C4><_I9aPf;l z$mbSJz%>2=H5TnG8mIzt(>68S_dDF14|SXL{TX{_Zsa535Afv@wgj3&cD4g=fQ^pC z39k-sFN1^PB+%&^o{IS#G3t$e!aztPY4$IY-j?jdOFLB$nO~IX<&ylvzhem-@ON$v0gV36Qvz?u*f_Kk|j5P_*f`apl8;Uc3R&A_*KA7dU z=E1mHcyz!G>GA6-Rs~Umt+XCH8ue@!s*6z?d{`#|%DrOHOi6}q-lX?P|BCvlZHy6w zN4k1vm@iQ_cbQ*}-K9T#an-%Zt|7C!fu0(!u@E&7|0iU=l8j)Mrh9};9w&-Oyhk;7 zLW*Ob%h@nh(I^E{`sr{kM!X3#U~eH(h~yC%uM`3!0@l8fSM0IxjCe|dg2&d8T~&!` zUS=6GKotX@rMY{=B)R%cMN~!$`>LN7Dzv_n17pv_?+?3FJO*cAQcxY($i!>=T{(E2 zr(RR#RC=>_x6S_>d9j~mU*)E?)N$d+*`B07f+W~_PS;o+6}$24Qv!KRow-N2PrRFl zG@jR^6tVdfu9ud1pm_w^hY-I2 zmR%3d@2Be@4m}OabHIXCULb(j!oGk45@n_+Y-S%OrPF$ZKk?oz({1~!@vI%wf^Ngd zb)NON!HtzK_PYL@C$iOd-`x1}9yC;4@XgJqr8KBFPm;SbL&%(Qxu zI+)}zdX5L=X$oZh^)^W-#57@Gp=s@nA&v|x4XSO^mIAv)MdJkA*%$TGr_fd`A-7|H zL7XIRqp!Bw^~yhXLa@#sGOr^2v1lJ2qdeiax6o8>ah~rrg}18vWXGbxrvXox-uTC2 zGW1XA#&#z@jmRkM%~`@b!F2y8pXWKnG_!rN^(dA%*k$>!A{52tZvVvjzQn;xVB$A0 z;wCtYS4tYvn)}|*EGH1nx4-SuRfjERKLtxZ-4y;}lzo`BTzC2FUmq)~`p)v(Rvt&| z*4)r{=~KM@hOIaZ7G_#>ymqK3jiU?1p-KbX&>2269UjQY3!m%G8TtT_86T)d3p{w} zRBrmBI@PTVA0Z-sWVCw2z2+UyWB$7>9vcY;^woBZIi_PRoUa+X$S1Uq73RrP7H}$3 zi!9XYO!~s_k}pM@6H9BiY)yPe}@@kij4GL4OMIiu)47zqd0-Z`r$T+aMy0rBW= z2Ss?|F5Do2!Cq_B*sFrup+fFIh3rA(oSFwwQg)4% zr5-!)CMdOcl%NEg5>yY3SZvHF()-Vpa<2E*9Y2<68#YzSjF77Rhsucx3wk5hdxiYs>gtTQ`n4X=X7T22y|Ai zSlsYifBnZSu$ju-B*+`d<}>$I1kcWFo3((J;^L*Ya}$H{>`5^s0Xb}e13AO1)>L7} z+9lZGJ=YJ6y0%hMS;vCVJg@<~b5&VjcI39J!Xqt`ko9kZe(6$#CxV1Ah6wL6SGlJS zus&rVNNu8r#u;!+3l}5(ayUVPOs_5txn!t14EBO^dXVlRqIfAAyQ{iEIZurKY7b1@tIB~GYH!8$WYgzKJG&& z{F)H;$*R0D|8>sVz&^1P1PxjZMKx47Tq_@&U}D zXvpN2mp3kNP-0y*sT;#mo(pv|9lq7)Pvf?cM!LoR;OBbO%*c&r@jZ=45RZww*+mk3 z&23ECPZ--Px=IKAj%#QFs*AKm$SA7UBd+VMM@JmbId6o2*tMip z|BI;d$M2|HvFHOXe??~YU2T6B8+2#E%gDNG1GXF6m?-u!QDH$9@wZf>93kY`)aa1U z^uPZa&lYq_nmC)3Wzdl=S42+#*Q(f%2gDbeC!NW@R%cS#zoJJX^y;z4L~R%PF8i@^ z(w{E7gha-2VoYe7Cyu{eXw#)Z##M{PTym*;M6e7}kyPTAiPx>2K%-x~wgOaUFaVP* zIU-}(FJ?sRom|8jC+fr+iH2xj#0cO3cu%OeQ@&vyhgSB7>8$yJFNZog;J*3G(lc!3XF3|Zt`lk`*PW? zD47lxwjD4~AwmKCx{(yH4GPX+p6wS00X^n$9A#zxJ$*&~eMkhr?BdEIT!PCfHy^Ql z$q#)rHP@SeN0x0a#|l4ji$<&s1gpdf8caVB$Z##IRn*CkWI5`-y&h3vmf z2aVQU#79{~?#9p4rOKK>@}2t4(~B3JWTGvzha9%6e!k>eBvEJFNTI#?;ca)fh zZ{+P}3DAJFZSZBJR~QD=Z9ajF=SZYE-$`OvlvzmjFhy~Egp#Dj($~6zt}aFlTw$U) zF^*AO(;zQ70{-|8+X~2u6A8$cBx}CHmSjJLZ9^E#txl#Y1Tz{xd0g$Rqb=I_hb2Ud)4jA-lV&<07F_!;Z! zdKr}&y|K&w@KD+kb5rLC+|9OsF>*1_6R3HN-rJP?v2~mJ2q(lXRq5O(AImKgs!S)n(hN-$AA>gIFny6-#6p-}867^@9Gp)Bsxp1@vP_>N&H5 z7Oc|`p(}>p6oTpTE4@B4tw?Dxl+ww#@=SbbBC`M9!pn`>z@V zMAlmyUqmM{kq)|e2NfoogE5zN|C89f1)U{r@NDzf!DEYE(bd?t;{ow-7 z?-S_=-`ngTCJFfr{N-WPdDIM0Jfe#Qe5u1?3~4L`eh~=_4_6LOk1Y`)F{CzfgDu5S zrq#>Fcnm;t(`4cg3C5+Y+SBV;T|kOPN#CJzyQ&&&MJW7uJ%f>J9eZ2FB6TZ`9oOh* z5o$1LQ99n1=hPZm()7iUEj^B$k&tT*NjF~Vc%F1f4Ds?$XZV~dUze^r7tjjfvz?Rg2PFNMHauk8pT7G3{D!mtv$x8{`Io59RQ|WNxC{A zoIsNUI+29eam0I_I3pwQ2uUGSRO~aQ7fW(K21cLk13%?S2fTrQLjDRucDQ+*)hHFw z$Asg*kK(P-6K%{P~kL;R;cBZ!SO+`%tH)gEVMY!mx{?ScImE*rt?H{wNb%oR5p zickn9m<-pUhz{356)(!r#15B2kz!CzkQLO}bMfj0$NaVH|H|`gFJ7l+=MTJ0?QMx% zJ4wP+f&^r9(I<33>?MAU2xNoBRf*9jb2y&ZxGB?b59uV7qdhbC(Jr@ha%g=*?VVq^ zA3jg3p$o6k+JjMh%r!KVmJQ>;s)u6`X`F9gxoXiix0ani`haaKP$BLF6!umD{$vwj zP0p>t{$|Wodnec@x2_#T26REnjMJ=g{rT;|8;K+-%lTwXNCX}^H@m23bDwZe2y8$# zCybmEsLzuhVP#HX`jmU>10by@ZEK~F z#1~M}eeXs+xlu-4eXwbLdcr?^HjtsSqBhk5utC=L?US}UZ=3sik<9H+k;J1c`)$qT zzd#zt!cBYu^YrN)r&Y1e9+Fe$aZd>xPoErR-B4Z?w+r~y!me;AT2tUM1Zla+WDftA>nea zYGJ!6;WOy&^v0XWKu4&hwPMXSdYt(dzYZBbN+<4c8D-QAG&+2%)=R{2EYrGmcEyC# zBkgQuaBI#0)kV=>Zb>-rW1lwe6{3FEz)mmDu6m^?yEo}aiqQw+BF4|VOg24t7Y{_L~R=aKT%s_Y$s*1rg7H@LQdX^kT4iHxcSkN~7{YH8_mObCi2>3=Jh<5OS)T#x3B^y|Ye< zBt+hW5U%>yCLwZNS`vqViw;9Cq=a;nzHuJDyXsh5%UT1UvJGBsS(JUuM2mU(Gsk@$h)r zyyQs_KV!}X0Zssg3mny9go>fDK&Z$Oo&nWzcgZYt99Z4odmas|%8(bQ!dpjM^on*1 zmzRHCEYPigI~bQd?g5(+~<-RrM8d0ixcAnr+_lg7?LM9V& zO+M@2xVws`FVe_C2GX#wW+imDkE^?$?X3OT0fC`G>>;BL@Vo33q z8f3|6e7M-|<4OP>&^5r1j+Eum@FV&<_0l2w`4-K@@}h^z|3vZfTK#b`+Ow@h${A&( z7^CMOk7X`rsmveJ6eQetC@|A>zmT#+0XwgHWb@98*;uU1^c4RSGm17pjOH z?4G#PE#Rqv#I%ptVVg#H5BWvtn={I3iGZ1| zY>Zp1Ta^uJE{TI(Dr=cVrIGa^dLYV9cC+#l@ZLFD_@w}{QF|!WNPAR#Dm+zS5N(L`GY(C@vwN;c%(sT(t9g~I1=ed)nyXZ z>lbdd1jRn$&WA6uO(>A;$OLb`6qm|w_87lUls(zb_Yc}{h(Pt>NB{8fHQKsT>6|bn zOK|fL%nowo9EIZte!prYJAyC5k8I7XB2@+54g%zg-GnNVV0`lO?UYL_~Mch5JB+g^EkKX^*I4 zUdTPYZwanBlefK-HPv}_2oz(DX0nEj7GvvA%gSwQ*})b`k@7n^`7E9PskUrP#|Oo1 zStWm6h2^L93_|hVJobkKpCkZiJdGX08C*HfxH=3*_yU?@7vP@4aY-YQh4F05h64}f zF3x+64J?PuN0g1;=Us6RE1QT&Z)e*BjQC5bq1F7~Hkbuj!(OBglq z={d=LLu-{LFC?)Ik`x?XvEEu^-JG$IE&riKM=~$b&WBxcL(uFNst?y;W8t%AqA-nE z+;y{is`R;n2yp>j57p`fTebd%V9s}|N&hNr8@v=uI> z^xo2*BEl?A{CKDwd%AL>Gg>J1i+%6*zi0^3O1TwsNw()q)Oi_5cr~#sM=8&(oUH<+ zA*q)p*PjuQh(n}9HXe4MkE?6k8=^WN3*N-lB-!K((Ia}?xc_`;ijAqWqWk3;hKT-t zZVh*g_=}W%f-60vw6=vKOZwq0A7W3W4@PgYmd* zW-m5z@*4iPauZ^EWf8g(!|~Rj!;2n@)ei9+tdmf^d)WbFsEdsrZ91COJDQj6*4X;O zsSqYWzOi4bEj?wx$v{t${CAD`+L2ujZ+im#=r46t1hw$SZ-3;=#wMY?!F4c%^GjlL zD{c*V|0g?RA4mSxK=Nq_QE4ST#N83Gp*jL|QZD}zxk zoO{|nv$(4UA0W*%nPqR@mwDA%`xoO-OfUuJmO2f|C`dVRn>1Ih3C~0*-`+2ws~A>S z%`CZrBYq}E&)kyH$S^(Qtl?!^4t*2)5$h40D^rC_=&Sq6M32`w3HqiodonsPjqP87 zmpDUgASU6*qNz>kjW*ka?3&w3HVo+;MEmvKIp8Dj$i3rN*a-3MA$YGL5G!f00eE|diYizdgc`Y!9zH@`o@xDD#9!+q zCNT#gUIiqQJ4$*X8KyD0WId~6&mj_tCOvL ze2vZJ_xlLRipn;`^gHMh#vj`HRRPO#I?0E(%s$KI_&;a{RO^zt9f5Nly1U4>&vMp~aN{n4obfrkY9$-0p1do9KX=S~t)aC=iWS=0a5+TF`irG@ zJHY0C1>UBX7jIDLTeYC@rI?uhe3eykzgs|3_U^Vh`%`Ed1`qZ-@+5~YyU428z_Ge} z@oO1>9zQMNurWPi{zs+H|^HBM=?#gfkj4_@g2@2>6<)C_13wB>x~YB z&ja3|c`K}(izCn?I=EdAq8W!8ZX{$7#r7MCMSvkWA{5gXK6bD)8!x0mx8%xvpNOJi zadUa35b+RiB0XisX4H_{NV;La{I3+wy27T&c!BId=&(IEO!y??n7N~^xWBy|sPvxx z$I@S)>(47msf)M}_zZO2Z2QEu2U#*>C(&H&SHM^-L+BL2LfQo75Et@Bk#UfgJMKup za>Jf`N~20Uq)L|}0$w&v1o%I1@h~zI9PCvkDhN`#Byhe9=s0Q-5W4Rf$V9VteyMC@RRvra18@$|z!i&2>SSFqImPNX}>fd&v1 zk21Xe()Su==&S%}`$z9^$YZ9#0O6#jM`%c`xrc|iE$$~JMSL+M-rD4B1O zNppWy<*Gotx%~%Wr0kA%_egsTpo%e@xT&2NfGPcPC&Uxc6zN>|=FQ#Y%OI5{o1yO@ zI?ff5UP_z;0E7-~d5h7o7y8a#^0yt}5!93SHTOZ5ysUq2+eA7$i$*9tRQN-dq@F8o z25)h&2zY; zSi7HLvm`KqJ6G-Q0HA{Y6hz@BQB6fPL7nL}ZH4l-Oq@6!wssS?-?CY*$GxEG`N)va zXvjw;^{BUq4Xqe?`|nI}q|qVyd|CAd^RH>NeeN6Rqi#pylMvRJvmZiW3?Qt!v67If z(*$$9F9)x7!Jw=Unq6c=bw&w)!4i{rhFq8H`ikSoo%(sER*YI@3fu5^i2}d#4YqZL zh-(KtQmAU{1_JIowZO{Zb=P)xn~mNP0muFW7Wf=Kgmp@33t~77`(-Lk3>OvpVGOHQ zTm;+<-m+Jg9JTQguGL_nl1%u(3n}=?a}V2Kh-OQYi%*TyK&;TQ9toip!7Llj@vA9J zns6zktHZpaB?ul7_G9=rti(+&nX(jhNokQNZT&ZuErRW2YEL?RhJsC5iRD##1!I>} zsp<`xWBImUdfT@57+t^e`F!|L-nE1Ga6$4yCR@xUkKS4|5qNmK=5nmqB|iwB$^W3vF- z%q=5~m%*j`s#TxA^poL?%AYC+8kIH%cFhy9Qp8U)>L4+*om+HajnYVwZSpfe4wv{d z3VJ1_j2`Zf1)a92)&MRmv2V#06|DZA&i6D_K<*y6Vw}lU%aw^60wwat1YmW&mMhou zl6b5z#pc(BcH$KTGd8e2-h~OF>%JFZ7+Ck+6Gtp{PzOQ=vG9}#4s*6dRbEswY{*$m z>}hlO@yz+dvcEd#7u-6C{XAD)7nP&}Hg+ZxVrwBnIikVE){32r8VXJDw#EnMbE{j+Q>Dg+sf-u~{ z5=@^y%6*;q0bh&m#s+!jPO+!^9tIkZN#r!Z*nkci%efE9q zvTtOqqPpxJe|%5{i3v!q(CMXE$&Fq(*Ue1HFSVHzkSk9|$HN+R_3Tl~TozMG?FD&; zYM>2zn>j@cyN<4m5g1+rWM&KjYHZ%kF1!<}^V_vY!z~adFu*&E)deYkg+`CHKPw)1 zGjMEwFuPn>qVd`Ikotm&+`RmC{9MEu)qzQ_m=yf-fqjpC1Rn$u3utJ4MC7*;s6`XT zgy@j6={0;?^7_kSdW$YKavP6x1FMU{s|@N}MnPSMQEQ+m#iS4Ld5Bhp^a*4;MaJ0K_ zj~xPMmG*5J`DIV{-SnTtU@RJTEp#|0(3IM;k{HV0HunT_&d5@!xu178TBu!0NGAi0 zd8oT-2L!NAYBHMsv1}hV*Q9rd`*tqdmgS=Vxpvv$3tUt4VUm_SZQO(`_PE;#8Tkh% zC0SxdjBA;7s2C~Jl<11eAU8+tv=oP$`;Ip)`SnN-@Skp<(`*U|wL7vB?Js1!1gLi5E-!4Uf zkJ?uTU?a2$uZM{JUb04~w-Cay?lTK@ic*ZzkjzC23W-Rpzq2UUs_qKuzhQQ^KOWtsx%6$-rbn_m66b;iq}AL)7ASP_YC$zzT!$MPFSAo#`p_hYx+- zb*+grTTTDjxcVtOMKxB`*msZx$NnUneUEc-HJnDD42cKLBDnB+>>9ZDj7u} z6wnc#5u%I{-oRR^E8M3Z2+AJk-Ths&zch1b{bI~8 zY)h?F%oSUg@M@M9mhXK!XpwWh`_3fO%!x7m?TjSmih+{=d{x$~u=mTPxl$Fv)@pDD zT#DWKzW-SvaVY)X#T)q;|AJ$ln1G*taq3y{+dlt0lpGG_gIsZDd!{}87y${8kB?gf zQLEHE3@9;o`9P4~)@}_y*o`@aY$;Vnv`E0-eKV}mYXZrlYiA``f`U@8Uc~){AFr#z zlp!}{XzyXYed%X``nm08bh+^AYR;9)8!NL_^>^X6?Of3H6R{5_SG`Td?HUXxKPj0B zp}B=Zo)~Wo`=yo*@LXU{+~e7PAOqnp*<5L{R|9s=Op{brVdbWIYMpAiV%q`7%`0)! zOMlDdmlrc|^@H+7LhKZxT(>~dL zwy!ur_2p2lqLW+O&mL*oD`qZz7$u>J7UVL{r@tp7_0seG2{3$T8TQ2_?1rc$CoK4VZ?p^ z0BT;){^4(VIZk!*(Z(Q6k0Z6%1LVpoO2FaEiE$AdNy0{L{vo|}Yf(NpyIAI<#k1-t z7M#|(SL^haX}3enj2o?5Z?2?V&7Bw{LWhCyg!^u)((xEMY;)v(dp1vaM<6XS%Q^i; zbK)Crl-M4h(&4D8Ww4x4^Ad!hu_+ecYW;v@8>ZYubwNe_r(L}SHIfgoK((ml6#OMD zTdTyg1?_;*jwMiegQwO$%m+naFJdnH`V(OUajTP%xX}4alN~(~P|&B*%K2=V^l!of z#rv5XawxO(@89m$JZi?8?w1HfWIOxzs|2fdvR-U&8919#AmY7uu$aKZsy{~%0lHCK zWb`T^j2wZ>sbiuZLHXTWBuo?N115p%1fMsFB%87&3lPx+(&w!4tk^1kj}U7kI$!?nZHE!YCn@9hQA z8g9cn?0z^ZU6`psD(@+DA?Z>}W?0~=$OEVl)Q8>Eu9+_|?sIytLRxvTw$SmORF_AD zwE^p@P`a;hZr}D*uKXM2wl>6pKe4!@n?gajC7!e4z``n_lE+>TyR3Pqm+LpY@5?o^ z7jP`*jurESgc!@{L1~&rH4byIYqS@fQ?=X_WfieFmI@Q#~Ti0EP ziBD4qqX^nNYwQGzxiR0a& zbnDl(E!D3QfYDP>l0(+r?>Vrx1A%_Eu`#0KFX{9MuP6Bz;) zE{yBHfxO#7(JYa8Gr|&O3Trttb4=B{K_`i`Ngw^6ZDm-gaLQb+xa|@swP~FwClQi= zIL7460vdpf9Gr7d=*wca3aaV#n)>{t><<>{1rE%;H_1GfT?aqOb5o-vOS!7U+EyGH z@UBK%>)3$LQe1AJ{MEx3-5>on$&B{FnOQgR>+GVhkgjY71F4$P? z2e?WkXMb&!QoaP{)lA!YARjIO_37^g31!k;OtJ26;SMo6IM3&?^+i)Ybxioi9RT$l zwth^LEx&?pEk=YdUAI9+n$BCWiC9?BbME>{F=zai=jG0P+6TM8kHy_(E!o$93++0L z|9YroJ*{Nplid>n)#`G3+2UDOzT7TA9k^rBIV?jsF= ztW(!x1}+|M(Az!uYKEy9Z!_jE5jU^*&A>h9jwTEwj7a%4Ys$&b{3lDC_a=eDi(Z)e zJp&mit<~tWTC|MjVN&-~^j-t4(GkFz@lPo^4P!Mwq(KQQ)JAeWFXXEdNsRpU7v=K^ zr!De-eRQ{*e1Va7fE1U{Y>j;M?023WAgiO_|DY0=Fq@ZidJn>&@|n7E$3d*@OzPPb z{tp7og3i9WhJ%>=Ti(Zh@((Qsx;QJKOt9eOJs`Rjo*k;328@3NLVTi~pvpBtA#d^> z`DAvk3}z5vbSL#BsJAD6#@XTwc{Q_Y_Ux6a>>1Kp};CQKZ?)0ic6zMLw^|O_!)gJGJkWD3J_o zWe@n5JUT7_(mA_FR8%3vXTR z^V}_JL|(sVB7ewUVH_;Eedj4u={+kWX()X=UyX4A>DZA^umJUIN6nQ z(&KfsUVktf{S4!}hyt|$6c(|TLrlMm)4X4Qyz?#6Za9f$@fkB&4$Z(7C~OgAz|NQR zkP&0*ig=8(Nbb|u&3^v;L7H+RNYH(AtV&{1+Itc|Aqjl6>ibfigSIDp6SgAiq>2w& zutv~>fN4e2#3{1B+~y8k>3s4{5P>RITfFm4U{b4QciOxJ56K_9wcg+@V;4yilH5s< zjHU3S7eD|e-#|#=Rr~u$31HM`=USk*^ch&CcX#V(rR2~|Ao*7ZdU<8ClI283Om3_Wt)P72=I%tOP4BfkPD**K8@Rbm*|0YWkj`@(UGl-QD+* z&agb68M%zQfup{trxichZ5n(C3MAx@l+hP(NLWc1s`5(nMXX z^W3=DTIyR?k&!h=-o8r~JE{)~|6npZ;R5{)jdq%qwsoKPY1U{7YQXx}j|4A)4j@iX z=vuu*=KABr^I5XQ!aJ$g!5;YTXz^cFdb@cHYkNz_{K5nsoXu)V(u)YU(93gyN@zfc z1aC}!oJU{cU8%)_WI3&tvFn)88+`YyKW!-m*#Zi}a(bw{NEI?qzZ_rxf9`^hmibJV z*k+hAGpbt4n((#+HxOM@Xk?yZ*OceqT9ikOQ`Z7mqj>fkO2^8MUB2g2wSZ*uP&N(s zt107Iey7AQ8SBd_Z^eghjw-~w%=M#LCE|U>C%CzTTDSgdT`kO5_tm00HqBpT*%vJv zIL;-??ntPQJ}IN97`?o*cx39cQ~c@gY$n<|y`RTH^Nc5QGb; zTVw`!^N+kO7kM7~9OjVEf4A8wa(r&ZgR@5+~JSz);_O$J+rIplxJW(slSUou%0 zig&NTcSzMbB!f*R;C{hP|A}WAyKN;U$^moWwlsZL2&sD*bth!yWj8V z2v+MRl;{n-B$Hm2xj8;x3gmLxxUo`v56TzxXnk3O&y+m-{FzAOlNFaZ(N`2#+1<__ zRCA|AU+35kqVV^!h7A1T&;s(a{Vjb_wR69$ZZ=YA_dTmYUD_m&h}r8tF2$cJ*BC+l_97Mc?rtnwOmKu|?;7mj@Zx+wd(1_i z7Rc-3?1R@vLERD%gv2GVpx z`?>`bp7jdN$KGF!u7ae8L8a6L?hL0-Uq7u?3~uv!?8d`SZK3zc)@Dhw>`oZ*_Z((* zwRC^N)mW9mpHItiwvJZ~JmvUP$^j`5(`edwGg<-MeMZ@jazHJrI!U{AQsyVi z6Yf^NEZhl#>xH8RIrU=(9!GvtkOb+p35=ZXL<=G7ZE1;85U8B$~g5p2E@|A&jdh=;c-3zaXux0-O zpP%4@ zCGL{8loCs0BXx2_@SD&Ghr!zK8y$u97`VVv`~3lK8b>5a}#RyfR1?EV3Wi^&Jajro(f57&&&r@Iv zWD8WlLjmLf1+G8_IaUamhUZ7NP``hO7c|m=#ag3@UCSjfNE$eyuY73eD0sM;aia^r?dN4IQh-t={C0=0qgFq3=K zlSQ{Ywf{7UMHVbVq8y84f{HwQ!oBt48rLL<+CL~W93vj2n|u8!>D;-XqNyx7kxI~p zG;yBBsWo3223E7L_d6~~tHa%*vBXvHF9#(vdpaKIGyjw#o_(rXKy_#O8YEfA`L_f5 zJ9=b+<0o)S+&xmI?_Ro>INty}vlxHYW?PqBW}ApM0|xu&|A$DiJ`Nsm9#Bi})qahU zlKIiRMiuoYF)#qC{)UCQPGkoV>AV6PK%_&@W7=9fc5E}SR`w-_bAingAHr+jCtwkO z6>WY~@LTkLC--g`L8ClKD{Zp8jxCOUOpN8+>l@2Sz?~i`meu z9Zhcz>Ka7JIxp6R6y(#O7W~8WD z8CU)CLLYhm9CTzS)w-#ZQTw44y#{^qm@K%1o?YdbRq(IpWA{-3j8zPyNaB3rAN0NS zs(zgh2Wvzw`1;e|OuXLL#qFHa_6Q#rJ9&b`u&G^eiTM1Jfn9s5z7=tCh5A&IM08`x z&}m%OX=)>nTq4Q7_e^Rv2pIAHGd0kCi-=XU`%01GO9v6!&_FS*dK+_167?Cj>m-G? zdBCT#=Wvu`MNv?)K8twh3pt1d{hGcRu!k2Oauu_KS)ZnOuNs|FG-bST~%tWM1^~e;FnhR#vL}2c7ZTi-|Us zaY9#t{`l6r*P9|rJKg@*nRL>QVww@J9t7vL&InQ6jbc<+p{@oQ|DuRLpav(qoHM@X zjh{*^V;vC_vn6Rc7g6ym@M0^`B%HTczSdftj<1>9xC6xn%>#K3diY^OH8TMWwYWT? ztu%N%$W*}kYpl~oi;@r#TG6tZ8H1(|HF@~*;2q{M|1rC5c4>~d>4O8~v!&{+4mD}# zBnd)SC9|33owu>sn}mJL{20re@V6{Tx{B3O?;9JL5#I#ae|ecfzbjZ?tMrCFoB2s! z3D=6-A^;F>07W!J$e|K4`Z`eU`G-9_a*ZT39sZf2a?gX6wuFuan@dhZ_?A#{E=ZTx z=}zmzom5PfbslISS(k^}j8W;4*Q#UQTkL6cqgOsy?l?MGf5KRc7Kjp2_ygVQTmE9Y>OE?fqXUKx>F*FsKk zVnIP0V)?7R%Q%`lJL*-F^ifBV;*ZyJxQUFFCMnrjH5;o%S? z#D@>T&$yuGuY(m?tjZ{j#g6!4+?LGi!9EOfpS~by_XCK(Kxts8u4n>!LrGdyBfcQA zkgX;oyk}GPZb*=R^+6mARI|OyC-hW5t@p}Zm^)-hG#zIW6=_rZ;WkD_eUmYvOpH zhO2zQSlHOyso3EM)4GmXj?Dt@g5Sj(FVrXi%%l}~`IUYK zlvx#nfyum2CHZm-<|A4=>SjT5qh4>Dz04+8=2$!sG7Y&n6)}H^A7J8WJnj0s(>>&$ zvGDv)mv#c5*ErP5#cX+-b4-aVR#6il7+9Rt<4Tl0ljB2s z|71r4xkW!B6tU?iaT0r?yl0=qBADiSl6wJNoy2ch7PoV@5T`W3!e5X7{~3fb4p^j~NZk{Ux$K!e{M7vM~0r%vMtt z^L46i$S|Yg!7Obi=7KfrU6QIS|3ESw#>h*qFOQdoli4W7@KTn&&nbJ&sZB7&w;D=~ zQKIa1shy~7=LqzO$f-+T6d~#zdt0qmH*+Y|Su;3e9Z;ib-i2u8*vp7b3I?g*=TPhi z6o}UtXt744jdJGJ1{KVR;k0VLEKWRYFE|d{CbEjQ;S$lKP1~#!wUA?rr zZAXhh-1B6K$JP8nq^)ix)oi1;_i~54FfQb$s8QrIRd7VSDO{n`UJ=%4`U4_ROm&)% zgH=R&*ho`ny>pneqP6{%HDtt#aCDR7*Yq?3^yA&pwtCFxoRt_EvN>TS70TEDxAa@l=C|~e5)*zGQWyV22H~L{1ULDth4vtV z)fX#*9=p0$AzB=LQ>B*xmQ_pWqtq3&U@>I940b6PeksSq4(Xfou9IlERvbQ2e*7x|!-L1K1$!<-`2Q z?AH5?eXTo^zViO_0&Q55mCA~dS1Hn4;i`G*UF^s2W0=^~)Lj_kY-Xj?XZl8EAZcm$ zw)U|3(~88)6_4=~e4?I(Ofw(60!cg;rTe%KIq754+>5m_wY~*71$1k)Mr4D}Fn$%bz5*Kn4 zWlDh7vup_aS*uuZK!PU-_mW!vdQd8}9uNq?zTHPUe5X(SidqiN&NW>FrIg8=@z3m- z6G``;i$F4!bU@b=dJMA|N0L(jg+C zw6uiM0@5MfU3bp?@8d3K=giFaW=-wTuNSRXppj{CLDOCFj}#eY))xUL@AP_$erYUA zKlC$JD88#qh*hCG7UL)Ou%W5PUNl3ZCX|=PRGp*0lQ$ZA=>e?2RH{_#G3s06T2CH6 zdn=@E0Aevh{^FmhrgwZ^7`#l5!1thWVCK}O@Z%K9JWp>BDo0Z+Tm*-K(Ao@{L9O|O z_K;7n4Q-(JHyX7aaxx)qfp^tg4@_tcc0rIE!Mf2pMQZRh(TIFSX%)Ej7ZEe+m=4<* z@X10(hkgjY zO3cEjsAST6R3*siQ^o9_@E6;v*ZWe4hxAcLO<%dDIl+sN_!R;!^oINKiu%v*^XEK+8^zjiqV%b)V6 z$pu!6fn|kjpWy8!%?xc%eDj;;N}G{fYyY&Kx?NHe)MX11bIY7FDR?l!tAR zt}CyT&p7R)2`mGUrL;o*lw9|oz}DgCr|9b>{SyFBnz}M-@k8}U>g5o`X{23@!l|u; z@CkrAXO37=H})Kmt(myprYPwb@ABaF zNxuTw^M*t3_&+Ur_LP$t66_e@Q}DK5+@=XXBgUk_m%K2qLnb2u>|5Ib-j0R@cHy*! zRA9jd;c5VxYfjg&qbuMBCbR<84?%)%%qD1V|DZw^cM(f* znMb^PxxEq`jPyO=rGs}qy~XQuaT%MP_r)35FV@Jb@;%*p+1Fx?8iJag-_(Jcl^vM_6~0!8oZRV`GG21ViY`=8SLn!uZ1B%2P;W-QIk(;N z4j?FM5!y)2m~Qt{|35gdabqpfO)wI=WF^NYe`pP+2=-XkOPo~onD#|#8cwE@i?^TE zOM83m*OTO(K%HmOruvrKiGG}cz%JZB#~=G>4sF%P6i_uBri7%jb7|#t__c8llF#EG z6u=D|RS4Y8s|op0XIpnk0oxWKZy8}wEd2Qv|AUz}eo|-RXt{kkI?y3HN$0#6Uf7tPU#r~W`mEx(if3ugZ7QtM8Tp9w|p5?+zoUz4AlefeL7GtEuWaC&Q&|Me4!mZllv z&W&6rI_V>O0et#M0&FYRG6BB}6lzucdWe>gNxi4hkAnKK2EzDc#rdIYuC+O};Xw&m zjQ}p&=F53~bTWDI<=l-B6C@Owhrq%jYaV%?IiE~~p-)wd0`=lP-E4y@BDt7HHwrzGGslb$L7sln6&`% z@}JJPdLLSj%_d|bnG1*4p!`%=7qw!I-CdRb=nj(eDNypfOF)LI;xwzRxc4zleO#9p z^hXrb%DUENRW=0r;&@qhULi?2((Qqea)4TDXdX&OD9&e!dK7OGTTb{fR)XQa)oyW` z6VcNI1?e<6;_i*j{)CnkssSF4_G}%d3J+r~yg~|rKMmRv)a1Oc`Q^XlQ*eq~`fKw&t!_pF!D2vf{nnI{$0>U%si&HIn5Rx8EArc=TE zo!}k;6xt~WVnJ3mnW2vk$!|iogG!GC!FDn^bzs~roEPaegpzgjStJCTBlv!FmdW>8 z7ksic(qAUNV$&b@-M~0ychib?is4^sN8=n4G5gjmuoV1P2(IQkg8NFNMqU7c*g&7! zN0zJ4wR&qN7bGqBIBUH1Xn+H{x`IkDWNYD&{NFN#OCa-vDipS869jPEQlONjte&z) znr|~$6$j=qx2fGnEnHgQTN)ndv^ae*q9h_S2T~m8EI;EqgoCXziw6?1LH19x8t=I=??4xX%Y;#1AO*`VPQZU+g=cIT06E2D#r3&|(t$N3U#qTGt3jD4u|NjIK`aw|1FZ zhIF{}Lc!V)m2T41Al01P2cy@Pjnwr!qH!MZ_$55SGoYku0POw~@R(=9Vy!L^@~X*; zC*nq+*yd?HQ3l`XFkS$-*cIFNB8zd>=1OZufn_ToIX+9>^1c$K%rBTIDbn-r_t(PM zq+rYFiv{nN`t7=Kn--*)f5TrgL)U_J7kGD^R}O+JWOm!`@0|2nTY)rD5E!BaL0tRk zhSa@b5n3D^qNcG(fV80;^ygK;LVYn*dY~34P9Z#6Nt4sfv0mL20aT^OwS7xj@f}pY z-=8Scv%m$YY@dEF$6gh_KjOKk7ZSw_ZaJG#1>auJy$TjeiAp#I@V5_SJf@CiiKUY3 zf;(w+`~931<8XH!-F8Lae zy;;R`83H+L)27}_XjX!qC<;;d4?*|k$f9HmAPJ8BpR7%DPI%6p+cx@byno$u+izUf zO~2s**?90^kEIB1QQBVB_Ll~ki?L3Ip~$pe099nd8jGly5A)@NrU$jOEs6g;Fqaah zu`^n5?sC}`4}kxj${ni2@HG6;f0z;mEEYY%@bk5fzpoqTt;;DUB;?0WHpdc{LF4eA z*8N4&JxE@S1CIMigII$iKI9J2m+BO4+?-l#B&!fGZ4p%pi0WFl9dZ$&#I$a##0Roj zixI)-Yg^#Dlz(-;Z>H7BXERLg*?~r$$($k(b2m{PSoC=rfYOgz*fkrEgH)1^pGLA4 z-u&GUv=P$XhBAXe^;FXp;CHnH@a+?c2Byo9*6zXFRPcYg>RZ*2vO;hIPL`aC09x65 zff(ufg;cM4{U|tSi@{PtA31aS`bSZaSVt3fw;WtQ&T zeY+KlEv$!^xxOS`pMxL>=H_kpxgnxN2h%MN7Z_@C=f5UiqbijGDxl<{*R;%g5cefJ zkArI%SA?nJ+@~7tXr?^m0Aj=od_j2c#A<)q1c*Dpeek~fC-o^KfqCE9SNeN8uMJ29 z!+s#pJ3=jplC3&7s_C#bUb+P+XFb5gRBr+1r%alZ2MiCbf073-upjk6>3YTP7Q@8X z4$p{lI4HF~C#Rz47&|&)o?YOgNR4l@P8^2VNEtRFf>-uGmrTB%v13WooRU3MrSDko ztFiboZtT)BvGtv{6OiRrO47qDI9j?XuKw|8A-q!^pu}oni`e-P5a92+iO6ceb99n^ z`5OXus`e@1`zECg8PLsuK}q{txik%?TOa>(1bmf1cLvkgKp+UhE^@6MZNz`1?-Y6Vphd9O|TIXXuzQE{cm;wQyXu0SoSHEwh5IVwJ3Ej}PK?>Bq9^ z&|4@Fd4lazj&?&rVgI&xkl#TVQ8_i(wHKw|$&&Y!j2B~FD-qYEn0Cj*c8MP&MbiM~ zh%G1TCI1<2|_Y$>|2q zH_iFI+Fof=I)UKg^?d%Mnn7tD-b2%eshy$d36>CX1J0dx}~e8Ff_2%I@)?%!aD z^WWjNCm?_;i*IG)40oNlX%12$C~)Xk#XEyoiV^^)Gdte_U5nijEh({CnwagVurJUC z7Fxr6rt*N+Wim+6hX!J7Dfz9Rz5@UC6A8aFfu^N}+rJA6_xty^ZMF%5lhFY6fIkF& z+274R$3#H{D>Hv%}j3qm6SYz)Q#&2SXBzX ze26lAUg7@P_qR`;Piw?%nIcM5l`P*-$LYqQ?7FwyKH5uSEgvPoEc8`Wp2Pjh61r-> zMzbbtx*GCq=X1W}E|_}@G zJ%%+xJLFa&z#WWQne1U82fOn^`7J8DSA!@!w)Vh7!I0|FP(DSv#Io)^v9Bzys_?DZ5ZP;7(fy?UetabGtS(Cs@nc4b2SMs1Y*b?g z$9Sl%a08CcGv^&oiJ4{*=!o44-N4CEhZ^W>RgeUj7i7v*k8S(r%pH6o)xAoHV2y1g^Y?g9{)oey9nN16h2eg1p80t4)LWhALm9IJJBpo9Ja)!q%%aY|J5(;SNYPJj7(pk|(+vJIfo64@c27mq z?t3|_uI+eQcAq0hUwjKLU2NTa(2M-1*v+x8il3tqgSX+`PhaF7U1i=RP-K`#(SWx8 zm~=MhyKnUy#Ot#iePzo{r}PmJz7}diSK;oiDI{R%QWHyF`sUFX!q&(goZ00dceD(k zo7!1PUx}s7p`?0drE*yMHc(eRhpG<*i$av8+pUzXhzL;%?1|4|1+XoH(hD+HZcGzQ zTUMDDb=6HWB-JaP>IG2$VpflB5fb4}Yu>$;Od1;FgZR8_A6TSYd){3q4v#K}UInk! zdnO9T1BUjn5*DPcPxk--dSua4B;|fzayH4md8PlV%aotyX~rrrcng5F$V3co)0s#))?(KRTMa$TNjit7f?hZ2R!oua24P)9w(n4`JkiPQ;AKd4t0 z6u0m?mm{aX$BP{NpX^N}JNF4y3$Prs8ZJzRT6*b~mft{V-0o;$RZFn+i@Tf4tsIYG zw$gECgH>dgaz0Fy1ACS}`O3Yrdb;^TN%@dm`K7SOKc4X!cWc(KKLmmMep!#MJHDaG z41$TJ`s!rUDqVzW6uFxdNo1!JZFinyEGY|os>M59S>YU%-h=~zo9@n$~(HT@?H8`*8_o- zNX?exVKFs-wH>tz6YOL!c(|?vKD9{AU*YXFQQ2mELXCL!o4we`<@SA_J%m?>PR@A( zrQkrc6gwIYCj7?^K}N40wJ!du61*QOnkz*pyi+5!n-T9^$E98XJ)rsP!|xrA?is@+ z_`ZuLOeRoj{@Lls|7c?nXN?0ZEg~DCX72zK-UtM#IF7BHEk4V2xv)yD( z>@wSW$-_Y0g0J`I(&f?!IQ++%!W%V`q_%d6TK;}e5hzE4YbT$>qARvoYLN&9$P7vq zm1Wz}Hy?C@#typ*X?&4Iq5gwKwde_S)@#iP0$-)zfK?{FRH0+7i07F zV}}D-{%29(fm1u6!H#uYem$zpQhIlLjX}!Lybnlr-U%$&x8x3kb=Mnk_pY7+;P9ZV zl1V)_Q!0GkYf#i{oWM|e@u}uIjVg7_@cBW*&AeGnO$YUT>PZ3aQr7-xQJmH*LZz8* z5=_5w$y1awoR=hVe5|@RieIRCIyi*P2bVyM^}>?A^#SDyP>_~k?BLicQpwHyFjX6$ z;U6HffmbOOrz4^JMLkJi472K9Cw5C`Z9k%fC7;JZ+B3VEJ#RzT61Z z@!+~m=gL$>M$lj4mz_1n4!SQkL-RqT0Lw;*$nZC?jNyMVqd)Hv;1G1JgQHns%Zl@1 z+RUXZr@ydA7#bGlf&1}KJwzI+Ch6Z=t0%|&mpD_;C&igzJ<*32DP7f?%um9zgXfA- z&{8FKWwCoTo+j<$bs|Y(%#y+!4V~ng&iaHavL1GjZ=hy~i84$~uN@JDyRMF}+EyXr zj=OA*cu@F`o(`kl+Yp9Dq`mi=>0hmAPHJlT$!)EXRJb2czW_5)0xu%;reBeUJY-1 z^DC*mS_=yhjlGKFK-=ztmaz#ed{kHbsbAd6ih@RhAjE)1+FZ^fs{jcWaS8H?^C|J* zDbpc{RB1ShG67q}x7^119Koo19!9UQ=I$z(7@-V~%y<7wcgT^Pt+1%gZp~pL!-v1A z9Pe0e|J*eY&iwnh4?8IpXqY1?*!%iwk85}>X+as8yWH{u06k-NtPK1`0BmSt^$D?KH5T^;{4qG`qbIX6$z(9` zh@S1^>7xR;q;Z;<%rt*crmC`s;aONyh$k0B9VuPl4WHoQMDHfd$Bkmc^ z-LwB=0ui>d@Chz0tZ(sS5~gYIQkbn6WLCns4_~!Ty>L44caVKF8XjKu2dt-Bv zf3#n_!{%RbPjfB|2)eC1{J>ifri9U>m3wj6OIrvORFdA!kCEblr-gD;o^4bn5VS)+ z;c=`_{DfZyNfm_7_CehW(WZ2jIqfSr?aL5++`^79408WTAiksAj7XY3|A+LqIVmX3 z9GFJEQ6P9=a594eh*=ndL9Ow|~F4f5-g|0LH|- zz2N3UB*qMMWfmWmuWUgtE@*OAI2qT`P{>*wVS1w;3exsCM_>5=4zwGc+0nOcJC%I~ zUGU%BIvxr3L~k?i)>{j&qh1TY`lp!&wOI!x9JPamVGKWqf;Ur`KQYMgQM~Ty6%)qP zSqX@SfY1(b=N!_-qR|y+h01XM0S#d^ECDCfw{H*{0XmLvewy7qf{IDAk_2!b!@T!4 zDw@`_Vo+y*44tI;{Qhp?o=O6Us0!v z?He#a#DdyDz_2f0UisCiU!3YQjk_-}jDu#efEQ%6 zNFEq`v%R$t8e((3UTv0%!*MMz$kprNU-^srRe=_b@lOZ~;Pq+17nY*%`K40e=BMJ=4(-P)ParX5lVZ;j4z!t-t^k z=Hw)BfQD}SuMK3RfxbP|-qjkPL&rB}I%7@%5=Z>si(S2!i0SHs3i0$=IplT%oQamN)?7 z|ApdkV`Af}IO&SXYJLz>ly(KR2oxQ%rtAyWFq{WEpVYZ7IW0O?J1}UUn!Nn!O$)RV zXfH%3`jzDsyJB>g=zX>L4syO_!dqF;BnV#bCb{U%MXoaq6g2+am~(zU;IZ+F^> zkfw{=$=OKJ9R(<4up#F%`UsU$tx!du2h_b{cd`B@O*-P+yb-V%Q-Vr17B0kf@bmTU z%%SV24{q9vdC|S!wpSjEMe_`<0qdHs|!(%dV>?cJ9Ecbws{tb`u~R7ELP%>A(CR?WlD${fy%cu*NHvZ?2&P%D}}ob~^lmETL!x_Kf5;SWQHzp7&m9%{U{lolTro^`AH-V~@)BAmtJJZl>%onslH*Ti@za?iAclIeIh-ijD73cF&Y87jcd9yX1{|xp zG>zbFdU~`qOiP49*`D$O9DO^B-)w7kHpQc?6S9BNv(N1*HW5MC!cS7#PYkt!fxi6#;W`3VHBPdnyBjtBYi zVuodvj2xQ}d;Z_=Kk{v4AIpS|YD>%iC=g(*BcRMQ1rlWDs7MiY9MI|((bvl*qEGYT z0Sr(5uL5`Yb0<7XevNFQO2oYNhcy7!andi_$^Q(+l9eTI&YLpK!3y!{kwsdST`MoPf3-9Je`#xB4Uj6`->(LNCF*y>V$c#HVBLGv_m)E$@Lat$l z?KhXlg+^i5(}4R(XuAV9Q%#cDjG3C}9jboq!N@&|QHo{L$(BDhj6R#+>T@l)iO==_ zvHcSBP@_GtU^Viu3MjPQqTjcQ7a{m?+cgh&c&D-=H^uONgpn)}mG99T34^VY;7T0R z(~Pd)tGrd`-;6Tiwj**s?=wAdUGa4<_zF8t_Sv8PAAzks(_gK>7`nEKdlHy?`)OL( zlJs1x@B7g(9V9{fm4+P0>Fy{)C(;0^9fIcbCXBs`APD8Lyjz~sL1$)JgZ}BHh6~HK z)5DgG48}tCOktPY+Fzi-;CVcKMo?`!>nA0+F8P({C%|#h6rm0mENmi;m*|wFE8(bw z^u|BX$!C;74h_(zBo)J^(M4-!F{%$uRKY@1()&&<8PyaW`UB%wn?>2FU=SrfyPESB za1Ze_C@=je!^i1MK2$uGBxu|~I|xcQ_{~nLSJ`o{o-5u|@-h8-5b%=Ypo)&;8Jp%e zzJ}*a#L^$aAG0UzgME^rF|hOoGM+sZRDIxyAV)~TrdQ;lU&sdTT0we+Hej-2Y>&mM zjE+b75enJSo{&XDm@=qOGB(u~Gv?+mk3SnDzW&BXF2vl`lkfNtVKh-S_&%gJp0XH}l?btq(l_<# z4ti%$>t7lJq;U|%_E2*yhVBBhrKPeV?)2;Xd7|2V?>1;YEN)Ii3jN##kqgsK2hv1T z?`Keh6vQ6|z!^_={*0yL7EACX|KLQQ116G6Wbuu+MBQIrh#?a)m2k^E?RR7H;)H!j zC%?Yi_wNNAe3Qj%Q5U&a9h=bIYsYMq=p2@K7m6G1m3tTW;l=Rjc!l7<-v?krCTnR0 zI6*nY9X`WOgxoQ_YkPq)*Wev7Z+)_7g#y~y%{fgPe{qtv0k);+E9E-mP>^R!A-w5dV}ZXaDSp6(TZ~ z;3C)Z*&b`z*PVepd6`o-J+`5?E5yNdgF#3c*!uMWf2;9cr@LbW%^=;aSCZgjO5#`# zBow<=wNSrJI}QW;ohKgMUO7%KLgz$L*Z0l5`fn;`|Cn6*|)bE^<=ddD19m%5#_a!m^AZ5Vne(4bm zE@Re=yhN4+4InKl#OJmd8$uqlE);_SI0|jvvpBF#BtH4i3La9Fg5Pc>#9ggEx^;*7 zephzc2Ln377Mb9}z%W3Y=TaQ$xAM&o>z2}fyNd^*6z;DG9?QV3d3E4T#%7nFscD6tQ@NNUJf{6m1!u=&m9^1-Pp+ltJfLR z8fO2EY;S#JUDf%aa^M4USBsf%ygOG? zaU=XLTIQ>!W?R6l2I3=7a6&usA_KLyV@>;<%G3b>Pyk(-#=0^@@X>h7JjSP2h2brB zOSBk=uBK;ET_Rl_bfdX9xX7^3T;SN{_7bO)8xh+V*AZPK$^!F&VAI2ln0i?)3)l8mdu|D&M!(+sXZsndELSf{4uDy#j;-x#222jsHBA8?&Zyx#!SF zm*EB4aW+~&6&*QeGNU03*q`5)rh2a6D0!|kc+`%1j9kl!KEpzmwdZ|ZTHxBoubj4Y zhQ4PQ!rVGX{T66pG^hGZt(cW?a@9-r&&Oup`Tm?!f4@kqoq@r{?x0%%x4cN%xP+5@ z2|h9srl`r^IR&~nT`-P;usVIRbf(ZDq1mU9g796K6pFcU^ox!Su>M9~^mc}#*yET5 zcmg7RB4P+DB(ncv!j3sb|BI&_;`%tKN>*zcpGCE zti;b|DC=ceJl)rRm(R&(?fZB=wJ$g2)=(c2cfP0SO(M|3PokBYXYDT~VI^fD_Q0bS z`31k>hM$`A8El*Efl*fA7TrI8Qju42Fq1`uHs@OVP4+5}Zt+$7W1+a2dA+bl3;*y| zKsYNA7mZl{1eFFOoPW*|l@KL=y2KHublKdsgXGeb1&!4bys|kJ z4K})Q?D!)ogBu}KyaZ*CM;LAmD~Df}JOkd{ zAkau4W0bGha=D(JmcAHNZnPY0d~#L~-As8gb3%zswwV_6`gGu14mba4PK^L0xAGaNKycuNr=?<+JaL{0DA8dUhSPDX$YK_+$faJ(n0#k0aoF04!6T`2JH!{Of^K!yBmL-FSQ~ zzB@r6!LYO<|2&k+g_oz_IL-U+E$UPu2gS0lx@!5q07+odXoc>05c-@=#bj1|>3FCe~o5D-46DHL3L|CrWVD zW^}@TenjpTn#5L%%Zup@DIdL1Dn@Srm_m&|U4D(Us0RFvo&wM(?a&`(tSfk5O`&2A z-!L-hlBU2Ix#%q8BcPNhiH7YTd2%^aiG^Ize(4rK2Ge49)I)94!3uI{Xjuylq+iH% zqD}PywPInS$TDWr6ef(RJphvlVXvMm21os%7=mvuNVe@1KCf3oW)TbknXV8&n3s`4 zU=$|B%;+A2hAVZ|x3?lANp@pM4ly8rf#T&i4Q65%ZLaLdFAdT+az%xzb1P$bwLSax zg#3itsd*QO5va`09;f+gt6Z|lwkNcwHvTnbK6j6GA{tS{CnWP+I0gZg5GSb}0piPZ z2Rh5Eiph@|D76{cz3|tC1sZkms9=oL2dAxQK9ivC#-rBx$PXo%fAtS<*71_rieZI& z-$>K^JK-GFvor-p$862hv4zlt9Q+V+4=Wu92A(!W@Pb3TRB#-WYBNfyC!{AT-D zOvNRsoGeHiTqsyEoH=Q?oow#OyJVb78%Kz{#+-4Vn8=Ffkxr+5&fhX_$d}IrO=0Wy zvX~O{*ItLOsc9#LbVEnm1%HYZemOh-D6Z_cY#+|Mx>ZCrj%Xv?Zi>4Z;wB z#T*u+#Kzl^)jGQ4w9sqTroRyL)|Gbp%1mKy6Kg@FCJB=2`eC{)oGq4)5FMgSENh7A zxIEXzNlCJx@pL9Vr(az9A(x7gULIW}N?(grDg2rQJ2?@C0n5C> zBRH_uA9-Y5@mUVEayA~~J=OM7&3|Ok2?OHWkMu#7J#Z=@Ep71U1t}Rp&+@ET3#U0z zT8M4}n2==M%y>3(n*MRHVK$3QHXe5x@SbC>OWj>q5%apM_}aif>}?ktjR1>b#IAQM&9xF8mt^V#aokx%H!yEf1c7uqi(Q| zuONPI@SY`iQuB*qU;pexE8sgKIU}XYYn(&xe7E)dbWB_S1>J4PUjpt>9Qd(THaBvlYB+!BF#BZ}|0q0R5OkqI6=T}Zf-&Qz3I&sK^ zM4&~ZTSA0H@DN3TQ(trS=-?|hai~)IFm!{}LZ8&x)E8|3kxeAiR*KspBU&#J&WoJ| zRXd%2qZN_0JrW!5^GQBK;`srD5z{+$Xbaoy@PQDk;+%0QYn1gbGKdglk0{W4b|IA) z<{R#l{_MB0y*Mg?{!!6X5311d`AP=Zl zOTO5%Mts2vwmVx(J7awgDY)x+!Fi6|(ef_B!aoH<$*o- z2S5Hz1NJS71GgnBrw8T3t}t#Gn~Hgq-t4rgQ~X1QQKnn|6dRm^P$u=YW}KtUOp; zc)K(FS=@J}vz53vg|{mUA)0K7J%fq>6Yt=Z8rFluKnm;^CaedQp@PoXd6JK;lh; zFP+9Uon#zh!RfP#>%06~3l2@=OEo*>RWDJ&nCFb`*{SkT=0`v~%PT|c5xbDWdng*; z0ac=-xP`v|vLaox!JJJPYZ`RxnU-0TNvN%g9NO^fe4{?!GUOrDw_=R? zEVbn;yWB8w`oG93;+;IiZugWanBLAQ%OV=dQQ1QIs-ewVF}KIKH2Dq|Doqth9{m z3N6>snIPa+-l+>R*CwT z{z;+rsTD5b1hO^8W*bh5)nL*GpU5Pu)tTX-po5aExjO5iM~r-{EjTpm@#HV-1-804 zBwb|FMi~Ab#rWM^rLxyf#ypJbrNy;>EZ z<{|xSKyFd1ayPJlv=^nvmfgO7w7VxUvg^#V7#7L0jSmp4|K-^DH zUTxNk;(ZS#-l)o_qaF%K6e@E{nzE#1)I7aGz@tH$k-&@`!ig-1ybPfgjjJN#jL{!= zzp}iv6JlrE7We* zW~JYt9CFPcx8h;(-GWi{9aZg6AU%y6a+9*-T5Nb3vZbb!HS?YmhXvV2bj0p2AIrH7 zpl>RBN4Sw*hHpV5_t_N0WcGaP(qq^_bB7D-TQ1aO(h6+;J zl{~X{_O3~JetkV)C$1h>4Ye$dkc@Da-;~>J#OK2ZYL`S`YVQ%vRB>!T&o?FlZn{@a z{DI06CzpXexwR`Ei1ktmC}bwVHNoSjL{W+;L6@U$fZvo@Ib}5z!T|@zsGH2eZOWA~ zi)+EI7I+ge?gt7_CuQncPxN&}Q6o@c^2ThB?2(mLHC;ou!W3m#*=i!#UMiq!X?P5y z;)~=n(l7WG0QU1FB@B(JQ zCX4GSrdCoTBJ26Xrz0)dieV8aL+gkV*~C=xMBu&bO9zXe8dQWi9K&L{DclC*1%&+e zv?2K|q4Mc|%TT{bo^5B>`@w6miP4XN-{!6V?T)CZWP&X;@ItYEPG9dlNXF4PX^5l_ zDKF5h^l9^3#fLaP>ecMDC6UK9eYJ>@8ha<42dar#U&)GCnnSWF-lhRaydJ37r9dhmTDp5a^>kUjiy=M@L(isb z0URZ8aFrEDbY9y}^lWX)`G&C-8xISWb!$gm{X*4^Q=xsdpyF^LJTVp%C9bl`D5F)# ze(W@cpeB*e;>Tf(cd0?m_Koxt0nrQBk+xP0YRp3<72u>WfluQRnUZ z(2J6pAx#G~OSL>)#^Dz-q;YYKh~X&5S2Aa zBy@ZvZoYFUA{(%BI(P2o9#LVR?p-&8*J~~V%~pa3j~LYy-uDkhzk|fs6Kz5F1!ZxJ z!QM89-Q8_BKiepd7SO_XL(y>J4Wa{zD1#-ygWBZFh0v&Zd#|IM?9o85IrM~)qe&22oFX{ z%=#6z{v9V@12sR63fkX=2x(sF8km+pd7Us``EY?ie72A9?xpEpc-_;eUv2tKBNNzB zkk2u5iPPVXZG^qZT@_KVyJ7MD{>JgBN?jWnN&oe4DJ&_r@E8sBV}dF zxsQQUU6+B!TGG!@V)w*joR+Q4#5?Pl7+L#?sTtf#dCqE4vcDo-TT;Dwqf_aDU-A*E zU>g$s5T$E6q^=s`@#A=Yh|rNI+a2-5Dh~=WoB-F;i4SrZX>~6WvfpwU>%FR)CihLK zmFi+%U4-8xpT1#jkUVv3r_7*OkWh42);(VZf&Gb#X2L#eeIM8z-CaRNxx^W-D4ngf z--0`4SJ528>E$N?t|NhWO42-USUe=g$jq$1$@|%@n&*9xUdx91gzS+^nUU_L-Hxe4d@Jm zFXydjtSIy?5FXU+I~Vl&4DySv9LwePUfQLvD+Z&tGa^eOcD3;9H`)z;%`G-bKf<}J zd(ls%^OeAG#PZFqMG6?-6-OwMkUF@-=-n?35YCkM<5I}x5}jQWLAy)kS4 zOg!hdWX!3-D+Jvw)Ap->+oEny0!|#XN(T?MGPdH(FXq2$KQvyJ#Ok9fiM{})7d+9S zL&R3;SMTs`Mn-q+kjy-jP|-TT#8YxmA1PSgi63<($7W5zlmGZ+=!SPSGBnC2KjD<} zzc@g-)^*rd?pA&iK)_WNe%1LBd1J1{^zwnK?zNHMh-xMV=aIKTL4)5jRRRTYI3a=B zoJIPhyCT$oe&s^I6dY-^_D%yS8)i6gKSK!%ucGx~gPYGX*C*FZujI>DkJs_wXu22_ zg)5|@KWR_Zmc$faiT0D6y6XLej7(khL14fwt^6ZQC{8gj%*dZcOYWs1h3xwg*|2Rx z<^1>ODDfIwd}ao}>`9h$1G=%h^qn=2{D4YFcSr+xZdG01Yg zPIQ$~pd|pn@7O&7OPvw+P{OB#;n@_+))*&eI?4o_^BVG{um`XhKcVsIYOr4WIIP3f zNeG@j0zCU4S5jEN8v%Z1!A8n|Mvp4fPSES&YcF z54>0<5oX7UQ2~CcNLahq>H4VC29MMO(F7-|zp8wDV~!u`=xe|kVzQod@YH%~E~2tH zQ{3lsX>)gMdE2;CeGsYxamQJ~Wshh#oo_Q?y$rv@vGl?WvqcWm|_X`Oof zuIm5m%Q3sDt!9Cve2A~H7gC77YueMZGN6e|;`Mo<+h;n4@p09HJqRKytD)#89iu77#SgUF-{B|3xSwqg zfm4z^Wfi_5fK2b51Nx^PuchmZL%s%-UZdbttvr95AWSbhy}IBuNQc~Cetw_pUMbU&6`C@l9Q${XS@mKHt*27 z%;?1W;L#XzG{?=kuN6>my8n-)Fb%t@jL1i|6diXYktLmFEc152a_2eg*PmvH{097L zLzXCB34lOox&jatF5ynkW{wqE-gHT#l?94L{{x$x5C7Y9#ii$$*=L$eeb0969OWGT zti)KIk{8T1M+eYJJ%KBbiZoGEsl3{$86cd!c^I@pbUqkVmOZ9th&rrOvL#YPQGgkb zI;jwt7inz}Jcz1W(})l#ni| zZ$0n#>yB}C44-q(-Ye#sYtB+om@FzvP4R!us$Tm>p6;Y3cLu@`j@vDCSNF?k4mE>9 za`Z?JbDK$42nk5SJqnMqj@Av;er(d3==owf(S{NKZmZlxXex73~;9RuN0Hpdj{Kmig!` zr9>RIEQ&^xZ6rZdRqH2G2$uB678;Z;#X<8>b_L(XDWa9fJX40!9#j@{2FdY1kq)qANNK#x z8;wlgCj`(BW;Jgfy(r%@?4W&Jq8p|cq9i}-zKfzHJ_M-PZMx8DHR>LgkZ|!DDY~i?{^z1eb|sVvr0z(J+XZ$ZN&uLjGmL_ zT%Iu^?7I#9!>JsxCaW2T!)#I8H9w#xuqe}@33ac2CeBUXqI85lR%Ys^YQ*wPWLPKZ zyT&x~GdtG5*1-_zK`$b-zB8&u@Kf<>>!M>3MX(YT;S3(@{uMTALMs~ELyrxW57m2f zO)lR&s0zJd+gAs42RLfIqLEd@u7bCKV}Z;5BS6akiP`1S^dWny9F;rh-jT8iD|UrA1uudtj>lLHR&cU=qR~joSA?X;b>~>!1`yX}GTh zcl=0GJhVenik7Y0LcK{>e#NWe*D$^zg8lK$f+^bC08baDPUQubff<*Sv4)tks1D%D zQ;$0Br`pmupq}1sVW!bTPes1yL5M5op6D&r&@KerWe{)3?H>BsMjoh2sY18FiA}Gu^G2(Bql|yI=*3W^I;6jX$=Lpi=S6xzA zir1p)W>fDI3^9swRMYxCNZ-ddK&gHFn5orAuYc)L^f1$!llq+;Stpm<+z65&BM!`G zBJv$N6rMi0sc2b_wb69M#`so|_rrcN=y~T4rDtIz?yUdZSEj`X@xz;9j!l}^w&Rcd zg3I%KxLY5ka4T&0_lJ0)7||v-BYD?V7J=($4bw{BqMaPtsNOe)_-1`-a)FT+{zGck zYwUjt_-D_mJM|yYdf{P8|K>~4iGJ`;^hZBvhJ6}FjuRwlzLCKk7aUwN2+{Ke%A`H4 zFL1<^)kMsIZ2r#zxmbG(aTy6>16GWOQ*o%DaSraJ;vCcVjQw}^bra-pH>rOXDwAn* z<>*MOiG?b3R{XGBX5gu%#NV#om*Q3w)85)Ms-~55OtD?HLcu>@Z!yEE)$`|1zoOPZ zCOI@!#;&C4P>PDVFwj@kcMaeb8Z{-AI;uDLinL-D9)1_>>P_7_Kzj)7pqcC=D%$V) zebtoiu)Bh1RYBJdKUJ#n%p^4$wu0S52tpWCL!ipMhp;34(0iu4CpM4CdSEC9W<2h6 zQU}c}W?cglNZ+Zy3u0=N90sQM_Nzg6|ARwc>M)Fq!BRSShvf;YmBum)u8<-phMHz? z%cuB+$Lwqv|NKXALWi*0s<4B6$>+j0xOM5+VFR1K4l0Cn^CHh%Ve+yzT zU~3+1qD%9~>A@|T*aw-f(hqROf@FHB2GWj2;jkY};@Q z3q(a9)!V5c>HLkd_dWh?z9LE{=7$d2mc`BO*_ochtoQ2uH0-k(RHdMzz_l zVT4@@+95S1nH&dwfLrCOfxep{;BNG8Z}2bzIql~?UWayQ8Im5}88mr^qMpg$w-z}~ zR+B-9}`I zI=S%US*-w%$a79B-gM!}>`25WV@0Dq=El=bwP?Llx3=~4c~IqeCmrP{ZGgX{&0;^> zaCFDvS)X_p=%HvB`cZy51qs;+OMf>HmO4ODI_}GZMe7uy)C9kh zrt3o~B=W`Qy!R4nK-!@J^Sh&&l9~HY-RBgZSk(XQ?r5q8N8U2#t)e%Th`hc>_0HS8 z3yE;1iSLuuav0wsvWbM`cxSxF4hszTYxT`dw1O z8Y*Rrvs9${`9XS`i8=qan(vA-Pvj`Ri#|i?`zH@Knjv9COYmj%;r$bubx5u9cflSOs zv&6+(a_HiRH0Hl8u$ujo;3=hf?uh^12%j4CMk(z!4Y zL)3gjZtDI4NcyzrHyZb31sxYis&6IzZ11w@o}3;;{{4H8O~{HU8P znX%V)mU}|N{UWmoLkEYQzV6G#>gXLV>SYO>Fg6=Tv9oy(uWI#;r)&8clGO-ZoSZ<# ze)OC3A!_At-3~HFy4IQ)9zfCKH;{}|kH zW2FgJ&M=p1QzY?Rp*%09vnifL+MLN-CMFfvMjhyr>|FCMHYD|${-iK;Ult$Bd$mSw zgE&AayR;`Dq)ReHD%_4bxS5Ri8}oU;crd!O37$IN#uu6DVi)&{Bhl;JNa9e*><38F zVtV@*u6KgZ_D$N8FDd4_!sxCO7ky}|>e`kaNZfM$FgM?gA5~M`W3P_eU8}p1`1*t^ zq#YEZruCOZHJe}2*;J1!VkkLMs&mVZZe+-Rq2iD($)kT?{;xG>yd2(Ni>qnxlV#2c zd-?X@jKM|D^1<&^&qIb~IVH|7pPC=R3T@{N)xDlY1+niJ50p0o3ii*)<{mj388s$y z$DhrIT6_eeb)gaLuVmUZ)#SuI!S5vKz~tV4^%)lNPgyLH`^lDPUbW`&39h2_llqg+ z-Q#>kuKaBrvL5#O~l3_V~R-Z2Kjk8n+%NCpp zEqCH?(jCscv7Y&PPl56v9+yI!g-~xL`}-nA2mj^WklbJ@OHcl(3krv4sFq$yd(DBy z*N>X$Fv2UBw#!tMy}#Ex`YE!<6tMp3QNXljIwb27Kt^=|2*yNu73_M>;(qT&oF&_! zaO?p$_cW;w$61`=n;&?Bh1#OYW=^UKgyAAA*A{B6M_R3>+x(iQ>TJhVws(G%CZ9pE z*VlGW!1ctS$(gFb$+3#U%4dVFUjUiH<>GKXmtxJ^<{Q}ZZdaXpAa+$=^^rXHw&C5& zl=l1axVr-AI}5N@AufP_nAC+LT`(yLDV0ZGSOScEN9rYr^7luj#*|4m%%>f|QKx8+ z7w_@H7td|6LNjwD?MSTUG>Hj*G}H9GlC+K+S>$4<^!YP}Febh|mH)d4 z5<-Lqkp%W_2(NpXgKn}6K@ ztUmG5R|UNOyq2Wg3agUxyXgeGZD6P&GQh)(zkKrhKZc3RH`TkaI>xbo*_;+P__q!A zSQkJe%Yu69HSPmn=HP_&>FCWWEE0CBf904DedJwFwZ6ig-c02(6qT6uUQWuB~z*mR+1Ww+C3Y&n&Wr^4AUd+F{xXNcO>z7)R1`gWvTn~H`*>HdfAwj>-=g+Yc2 z?2i4&S0Ju;8m||4(UXdW?@==n9WMQpUfU_m48QlGP|*i|-naFu=D}B>Q#%OpqP#(^ z;2Hl-h-N`wKRJr|OwW=hSn6t4F??V3%)vOurbc=zdE`vA zv#dphJxBQlrfD}}(UE~{bv*7@80m}_v792#jg6ywTj%+`GQ?uAc*VeRoCw9`>ptmI zCJO9)U^*HYf_=+1{!*tG(~eJkLK6%fW~a#KB6c?wCVfElZ@2k7p3DhCo;o&ogA6~I zEolxSLRQp1FwylSPp!6T@DrpGsKvaixq=^*Rg$ct-k#^$e$<&VSrW16jUoW13t3AL zBcpjs=+cnzJwM_O*Ld3bVs)BKVYijs12M@OwUtcFj=(XNyEOh+f5^%OFiw;AItxkC?M+d%&OeeE< zx5Jg%u8{v?v3j0!ljMIl#0%(-1g6N+m?$)a zB?aCPZ_?u!FstWs!V3OS;)@`YE-9jrOwMQpExLK+pnZyRfqh^_`0-be9b7|%tO--X z(u;^S;CGEWq3tvKFHb~`IexK2oWuU-Cu_M!r{a_O0w()iAAb``ES3g$qK65#{-tY? z%M>oE#CfA*qZo;vn7A($-D#LmnbnQ6nHab>vOuT0M~`V8K{oUvYF|u{cdIJtAa`+H zGK5-_<{kGPfOKiN7`-{sbt-@2I;P@Hu>W*v?>f7-@E zMw|&mIh7#TmN4WaeNWVtIUWFuhhuy4I%_l0ol=3}wvn(tJm(}^&Wugf@z1-zpVB4Q z1s`;zFC9f-nQ?Xa8}ozQGr2LPC>3WVCd%8lRHCz;SeJ_3U9eDZ9ma$4k9#^Epo7J? zF5L+kM?h+vCFP-{sXbP7ULt4G3Qp&AyRBnYG_A}en2C_+6nKBzLKr}5<3D=MsMY+6 z$(#vmJnZI+gH<*W4qbDno7|vUBOXDsnGM=_&1i4Fjd5Vbp8-!rT-2cd9FS%D#WacK zG_jbb6cl!97VMa@a=7-+u7)GXOvu-VA|G~$ifqOjqalwB5D#i1*dZ_VMnuk^zl9#MgDXKb8ElFpxXc$>MB%&1WRqr{ncAet!teI+`OfbvCJjTq&Nr8bOzqxdDc2RG~# zd-47jUySK*xDhc`pdcdM__rwn^1L+>)8`LGLF5aW{J{=Zg0tmc;%^7~AV;jt}<{lHygcvv+$Lkm+ zC%)Ni0P!zhgdSjknmRg&d+ucBCkL4-oQkNycTABPi6$Jz`Xz9u4Hkb|L;GRtn}BIv zTbPX{nHH>wM!(Q&S9}AmUbyY^+?Db|yZm3mh@QNuhZu0G0E&+1FGjR?0 z)fj`h40N%LB{h_Navt_qX@(m4d|En1RFLk4G#T{q4HSPLR6Y8yzu6N4>jDfe)(SnwYx13-W;1w!SK9INe{i7n0;gX;vpLut9NkK`C0cbz8f%s|{=|i>p>M|O_ zz^m;&*!X)(qEPso>n?hk-Oj zq$lQn8Qcmz{YXJ-Ta>&f$ptnyrLm>qrK!ZoAM%MOgh94}eI|sh?EIO9Vz?wNB?vlV z8shYYdR|-~9=sWir;ZL}{p1C5$uprwHx^ndwx?K{%Rgy>xTT7~udgPSA1RbX*_+>` zxg}G1U~S;`uOFN~tSXTA`M=&%(e1xYou#2jxL6#nFDzh$ZxDPTHUv2|?yUvYdR@&gnv=q!!W16 z$Iq|`t-N=DI+a;4C7+?@>uV{NP-+qG<}#Q-=QTWsAnz6zF%w?cDzR-xJyMn=80=nY zPI%M#@8Z#`+y){>rQurTI0K`SB^gJ zg;Gww;>K(-1#5U3RaHsBI66CGTIQZ<&s#w-`*crzO#&A-TC7Q>rUjCs#h?SbG?F5f z5co@P`{%HQK&%Y}OJ?+kn8_^$zWzxY%9`WUukD@n=eM!(;%emleC zUJQO*#F^mpk;ag;z1puKkthh##LK$i_dm@ z3MI78ZnZ(IzhA8-KD8;UO763vR_PNXjuiNW5p~S(6#7Ca5z+_$4wkPuD4JTJ=!j0R zvDEo^VDZ}yIls+j8fpJ%FT|Sp<4Uz4ijAU!_;mqO{HJJG7)(^LgV`c-N9>%B#qCt}VFya4@vJG`waGbUB^mA8i%@*YvcN z5ouh^h-Flb$>SE3lWPPBweAk2d-7qwUg;XWx1s-*LdfXI(FM%pb~~~jxj5TKRg3>I z@)sqn-DOe9Fbn#3K3b0_3kjd?INwP7i@*BIbk2j&6h)b|O&Im3v4yH0F!`^ghGL=) z)~<%!$M*kn@cAQ+=CnNmZU~Hw^NW0SnM;9OT8^CX7HA=pWx8c)9F_!CXR}(uUFsh1 zWY6CRg0zW=SJ#8I%c`qaagQ=5!-y_J z*Pows3y4+ri$+Tyw6CfW_IUui3_{!AcQ8%y%1;J)hWM4-|vKxjPhf#l2Mm z#(b;RKA_m!Cq^mTW;N?aNVtd1K>mJ#j$$TzB%LQ6z+_#Ogr~L0Gg=aPbM{4ogorv) z6Mv^h(1X-@Wp56ga)}OI$JKd7f5Z-|*z6=_N&HzpNGkY9_>Z{m5xefE6g!cQO)E5! zy4M3>tL`wvBs!Aj5c>E9e8xI~9uK6qcyp1(5+{>~hECx+J>@TIcd6>Q+EX=tu|eU6 z!9LG16Vi2KSaeNfBK1BOG%DXqk(7O0vIoxT>D5@frqr`OKPJtL+zaSj20=5^>gxQ! zj=|Rw8(~K>UEoM&0mvoQ^^{Vtk!=A3>Gf; z94b~T`8z`c?ONws7?2)5hVH3cKK|VYU+gkb3MDQ3mh{ssxm}q>;4OEv$*@4r4 zu=GW5M(@a8j!WJe!3!O%rGaVfS86q~L9?!&qk>rOTIwVQ`M3n|qE|M5%}K@|U-D%6 zPF4obN7t~KjftehuR~Az1jfZIZ8@2+yRijH{ObiOQs7s!Mt2ANGmcj1j1ISgI&{No zyFKUmQWruE9iS}`qf-C#?R^-l(w8TsKJfG5C6edNbYHaDq$L@Y+?D3fSiNZlW_TdB z;TtYFwr{_wOoq56V|uu4L5V_3!|dB)z1;*n^LrDJ^P=QH`N*nt^Lob(1s6R_)o;4K zJJ4e(#5^XPe~*jUhI#)9-H{dTL~OTZyWQ-rY8eZnGA(e;yHP;G@@K#ZfWky^vF?bl zcQlR5&_Fs_CS}@WBL%mhU`^;2ROL=bXAAf3_ZHfIzAMEKxrbo!jKIHMV3PE0x@8H2 zFQ!0Gr}=p;cAq+R3J#AYhHb&)Pg%uGIN@qy2fZcbmk8CfBDEZYe8&)CxuJJ`v1B9b z>88|c*UD+i=HrccVdO8%>_jgjq&7iUlNNx(G%LEO;V1SeBuqLu&moW~QYN_|wI!4q z_BBgTncFbbQGyQHRti^$>sDV`Jng4P~xOAw{-Ly6p)Jb~(7_B>+%O;AbI+epI z6?IN?LRq?*Z`(7tl~P#gK0J+20}#{3pdB2bkk&V=Se1CAzQPE!iK~;!)y4AkzlWOi zbS0PW=Va8vC1JHN|5ik^kvd4Y&&QPQrouD99u4J35{}i2G50oJmjyAO-|r*8^DCnA zc>txZ7GdV{CQ56mb0T+Bdv`7(7Q7oqknzOK1Tkphn(`7gb|JiAk;82%4gN8d&iDa? zj&^J`TV%p!i6cD3S_xoI|r-#+<66_Yok{0TwASv=`ru^tM>-cO}amIPRPWA^NX0Cg> z_-J2uo@5C*Ifj&l-FvJ6Bm%KZmjGIgl+bYiN!9_6O}aSRY%#G(Q0ZTZEkL#*JLgQm zeA#Trq!;`Xzwd|rWI0>3)_WP$tOj5!{M#>ZCwzAzsE$Z0R zrgg&q*68Hes!Lp}J|?-S_;I;+!8ck1(g+u?$r=1a?u@j5qXOg8G8(s6tL482x-kjw z^Kx`uShH}kA{2jBpp%T%XYo4F#7DC7;B#~33wZP zilz2Ax5L@|NBd{{Fo>8e_bcoS5R;UbkG~7sVAi%}|MKfhtY&32i3_C=xTJlC zO$)dCU5Q@Am<^Fmh^$Cgm?)MD|Jr8RJy#mEkQ%zrFT#@9DA2kD)j~StHac@Uj57W_ zV>SH=v?#=f=HyWIGeFuQWgV3OM-9!CP_%$7iWS6;DJ2|gFE7j?+n6L8Z7LVCdop}$MDEX&n74P78ti9TAkObYCbx>x-_Qe*6 z>sK6nt~G(T8riLH%=F<7eQu7`0zw`la62m_h1+=6CNL1}3zos5d!T2Tv1bTNS}>sdc^YiTwre|D04mcv4 zuDCO=QyL<E=na2%k;!G)=uKw)GLfu3NaTLz zs!Pn1X^oW?#)%RG=Xl#pe(P3%pneMAxnSlLLnN61rCp;npZ5yBe*X&ys6Y4AFt2kw zZg3F=LmSw${M1ef?S%iXBb4nmudm?X9v|Ls{EBguOVH2;9D@HuK_aKM(P?gW)4s7r zA(6iEpoO4i7l`o(7Cbqyl*w&5Pniz$ySx$*n}|=TZ|Sy>$CCIaxjyb2Nnk@fFK)Jw*RvS=(fQB_WJD9llM!d)0K0mU9DLcl75qO&PQy= zM?$jMd!Y?JMDr_AMHG36-n)p=eY>FjHxwzXjQ}S3)-I-YYP^sXBfJdrP8wa&{o&0w=vzsmu+%UQErG7PHjAivqz6@?oF%HTw}>P05nO04wDMb zAxy*2GczORct+r8{2e@jd?4yqh?DdwiZIu(KCjHi0kav9_~85_lSnVOGd&lSi}`Le z>rs^kS@%Y>hQl&6g8LoE#dhiMPAf}viwlVFA1^-}VmrrH2`N)y$b~L))*?RY9C6T4 zsqYm5sWmLt>KA%v@-HsJVcDzaDLd7AGJ(gZ?^mIwO95W4$TPYnR`zG*tmsrP69V>Q z^DD#4sS(j+?V`7yCd}jt=<8O0=RX^CYAdourJj#ypD}0Ksa4R0Z)aP;gnp7?0WXBj zf6W7{KgWNMqpFo2jDqSeeIca|BZyx_3e%O|5!;`1%Z5S0+@kJ~V1G4)R$7gE%G>O! zU$|1MP$@HwNM(6C(w3B19>6q52cB~zp_frrs(#A!Nem>2QeKoc*NFCgT#k6IW1&)N ztwg~2DWV$}^ezj6*^UWRh!z*KdqTV16T`7d>;_qv=if>@da6!vb(y>J)%owlqQTtgSjd86GhD%O%)pyGQld8$Lv% z#0jC;4UQvJbY~#&vxU$XbDK(>tFerH1cqMY7#j;PGTP+QtEN@2T86kj>lYog2nIEK z07m}eh`WNov;bOp#+z5qCvL{;=^@q@u(E~Y|9g3Gz08;B=>nf67ov?x_tH5)+ee@l zR;`Dp_VG&0)<9cR3$q*lL}Op4ao`Kw=>-^zu1EwSAk?WM)vQ4exqR=0|GkRB5IYYh zsfTMW8=WD@ZE#?Hl*U5L#I1*k_h3Eb4Ag9Cs-9ICH0rH`t>$_F6dagjUgK5Y;_+RL zE&0MvKt#EJ1oM0Wp^Gsy07eLkJgKzrIzUBZ0pwbLL-EAJR+GE>#PtIpoI=%|8EhuY zRBpF0?mL8Xp~W@;h@=L&COyPoyr^y`D-8XhJUzvF09?XT@cR*|f)saS*{yd$F<}pn z4`2O`_dUzZCbB#`IaIX+i)#omSI-=~Fg1K|K?4^D|L4aCK(|P!NfRY*ha&l0+ zLL*A*)1L9z{|(})ON05uCUM3(60NY+^Ca3jqXsVCfXuD$qj}e`=TPTt9=Ocbm*)8N zFLu9-1Se~LYoxv{g!|G+;^;mAWYv2z#7Pahr~62)1ZD(6d<%V;Eb|xPJ(*s zk1@SX|9En~ZW#W0X$^$RlHBfu%D=fk<21s7!F>Gpm#BT7sOOfIZ6-1EZw?q1qyIUL?~1(p4*d( z?B~#+tbycl!|E6$Gpmch*2RN>f!myMW7jU!Mw(Wj^Bw~Gd|R*>@$Jd>lpjc;MRPDb=x}H7_xm#nId{Dledx!a z-hcs9s)oldbm}hy7eUH-*BYI_M1;q(KQ4M(?9iz7_U6(LF-MxW%=b2z3=kkbtJg6^ zVnRxb)RVesDurSvUnlYtYITHj!LrQ}>QRL{X^B~pWa^h(LZ_YV_d z#(Awf0pDBe9)+=Ow%hA@Xkvu4dGBbooAB=9ObEp!O*jheKE@>ZRlEPl9H4bC8`)<% zrCNP9d2+!GJ<^E#@DXW;n!d@yw>asxTX%fR+m zll@O6`>D4Ts!25n_qkz^rJySfjoTA)nw`!IL^Li#gt;?_L_Q2S?1Q5=xmeOvh!w-& z7{x{tc>W%t1E5u;LZQe+S(i_N0@p9u%IvkQ*Cpl5jeLH*!C2fCWO-%tV9Rr;PzS>? ziHru4FaHJ67nCbT;;7!hSVt!oxv?RVx3-&#>n%m~pNf$XGJSOlMx zXNJveAK|-qpVsbatNL+XVFzI&G$1Z%iSQswHfoOulsL}bs&E*2l*7AoN4w#spEu=_ zm>Usy;SCkPI|Z#wahtVr;2rGjXd;&WYop%F1>bG1nJ=DYA33Z?(ozw=J~v#iWTaN% z`@Z3*rs2UjV^U6wGoX&IP{l_vt^`452Zr_9J1dt6xh=VC@VMw~^cWKvppMKAUXs!< zdox9Nw`C5ne@N6WY8RhL>Ps8clP3Hi7CE3F*8siZ0?ev@lf3-h6EE?vk|sqxam_neHsM>q&%a;?*7%AZ%|{wPT-rM#Li8P(sDjC(jP<=m9gAk6y80wBRsi3vkXNNiMJ}cH)-5}vmLOf8WqY2+L=gPM~%`d z%AQxL&EAx%|Xj9AnaHx;dpHYAi#4lS@Dl)LQ*i81})8Ci>v?tgOJWrAfNeyyx`{TdTfG z>4M!X$^109Lixpeb_-EDh-kNVh^PTe2JxnMH`uX zRDnoU2w}*rE#2~=MK8vK`LkNPabm0SC*4oud=>agA!n!Tj|zgbEp{pVz3$V8GZ6v3 zPxAuT7MXYKS5Oldte3-|i%$g>2ySDvH@D~Ac~WE1_mTF=?R`K?j1&{H>t(UwrrrGx$XdBAHHB!duQhuNAj z%rQyiR=@ZsMpK;@8yue7{rb{C(in+DVIk)%Nqh_rPb@^F>POhb?p%;NjP{s_sJnnM5xHHAd1ned)9f$J3Yu*M zc`HXMW-xs2)`@wmE&HAr??s)ydUsm%f*$4?6o@88u#VA6l|XRn00g&FfGjhMwH;9? z{HB0)NV*?i`_;JcDvron!jqj*s@lJGOHU`bAMUbGOhzZsEd7b#{J;c=5=v5AW-5j( zX_opR`3nQp|2;Kk_jhZ;T6b5Om9H>kD$zf~lo1j*<>Y3~zfamw6S)m=(NVzky5oGa z=J!M>S1z3PYQwE?vHX}B$RoSh(Hux6F@6jg;L*un%K645Fgvs*V`a4c4l0r#%@cHZ zHh)P`W_Ab^_zFR5de?U2h!7E$12nhqxPM~>Y{%*g+V;E&-CDlZXUWF?2cItlam;(7 zHgqwg&kV15xD6Xsx$Nc-QXS?OGO|$mQb- zz%|Eao+c6JA`r4aXI?G49}6#eHu45zD`V35e(+-$pPch|nDFV;gS!uXC%yu65yiv?cum}Sm;n3cozkZ~AU*Cv`=Ohuqe z*rgF^7}q3@_|s-(@#@caIp@#oX|hG@K~A%@6TG3S9V~O9c#qDbi*_?xzCKxk^i1LL zSPbvi?rcM>QE&26O)Dd!-20SiF)L2E^lCid5VkRYcFGU=q>J1i|O5a z{5xNK1m83>b*FY@nIalz%R7Af3a#5cK`*vBRy7to^vUQqwaG=AnF7*X!Z(Y2~1LpTD;hGaY`=kC)cUVE_Y3fV=A@NibiwEae zU3B-M2+*{5d*rjb#5VFQV<$%HQ47{=y$e3;0SYllO9{(p`LB5JPQW(cm}gGYHgv9=O%cTG#=kg1uuVXOQ@|}~e3f~Kk%2I;O7LFHRxsQ+vcE29&5f$bTDf2IkI7Uk#B4S^M^`VhR1#DMdI{Z4ppo%$RvML zuh4?leK4e|-F$7iP21=1jqcaVw<-^Wl)_x3r(rDY8<2vz059@SLse#=RlPL9)L)(F zzGukIWE%Qt?BS4i)N!Y4F__!j>L()%P&H9Df_y zG2ty@X`57@swf?4`OxRks<W+!xL;=B|0 z7d^@e!fFo@5}23%=M(DDOk51|Et5k&(JVy2B6`}@fozsq>?Lws2%|G$Q{aIZr&-#M zscM)p;cRC}1o#@EhGiypmJ{4wZ2046uq#lUjRqr-o3=43ewZt!_075G$!$-g?Q_++=smUb^Y-)G#NFM)#gv^fG)X4uho-buBn0u z3)#Vv{Uuq?l}lWmh~wr6DioSE3znhTvzy4a5S6ntUJ;`NlCC>=gvfFgGmpYo$o3ji z#W*8gz$J8~Ku&0tyB2uPr!Q-HnzPCubaT~g>y590^=>Ff1x=Fn+f;?&qlsEVCZ#n6 zsfb-$uREFZdOyFVE4UtI7u+G)oL$81dwh93p`HtZ3zM z)4F{Urhw&tOolPrnHH8TIWLoppcOj=F_IbjLO0^J6_b!@<>i@VRX<~yg~WG5NrCv@ zJ~H%3+z3(zqFB4wk8S?1)>`>?1zEN1f8j%of3E(rH_;W@`!U0(PsVBwqtYum-B5M_ zM?|y9IC_M)yuh=Q?51vR_Vi%HUmZZM^3L7Rj?3vkMj-k$$)1Q*&E5WQivywhx68Tf zEoEif#+{^!!=TsaVb3^{#-*HzieqU$IWT<=KQk3kNFf|YM6ttyv}wj}#Z;L6G&C(w z1qNeyaW09+Pmefnz-eN@8hfqw8-1DNAR*hY{Biy#=V0XHLGswdVHTC}(@A=uwiSG3 zVkRW{vH%r7IhmPr6Agi&-)+vnzW4wzbu`)&@;@Zj27iSuCMjt7{;$s-#Q^gd>>-H! z2sT}V-9&$x#{1Cc^)EDeCI$Cipj|XSs*>Jf)ASwuiLg^s@$;WXT6oN&ihE0`^;M`>7fe@~` z7=zf;fXS$fTmqblzamj?W~uDD*_N$zPhRi%EJEM5kpo?AF2RSKJ?qZ|d*TePwih{& zf)3Rl|6$zpg&nCarZ9pk1i{4GfXvd6DF2`qIS=9Y-1g+2NN<^bU6F05sOFqwDEeTx24{G6+%udD86AH~aQSb>UkeCC3 zma2TSP!1C?J24KxR<$gF?A0sn2FNd-$Kk%n&G-7QqBlYnsdk#B1hTaVSu6oxX4Q9$ zFcnEfjD^9p!3dU%3fAbX&isLR;AOA}khFP#?9d>?hk;m0XtU{Sb?|K$(-Inn{V_?t zYGa|P&;+W;+?{vl>}0nCwwY=&;W9Xi z8SU&ix32`{O;mx_c`4}CVi>Z`&U~(*osUaQ{0%l1l*n{pRgcPT$KwXL5nKP z6M|(*52}z$AH7FQ%DckJWt56Lwf>vkO=k^#njy2UoB2HZ9apwGcs^~lpcPN zn8)8B%R2oS9y2C{&n0D$@c!MbA>n`MgAXljQuBbUG~G^eU=k|o&Es$j?7tzOj9srp zyL0DhoL}J7*!T8s%8NL&Jt~;qXs%M)P$eyAlZZ_rXq+O?9&eR=SQ!=`S1&hdn-#cA zy?K*C``Wg5L1oVr)~u(1QDeIy;smpvQ-ltt=uI4Iz>kv)_=SE$oo9Su58aKQQo4o1 zSZuOcV*I2QCcAr(?N0jNQf(ukLRXreH~J4oA6xbN;Fs5d_tx0BsrwL<5Vph%KNWn& zErC%l8n9}z4SlLv#W(W$h@uyI>oyoy$OgR4#QZY`%+1}=C@2O0oyGJ05u4aTjCu=* zUGdEnEQQDGQwfWw2XxxuV9v2Qs5G_yDavXEGUJaJK+HehE3)x0K1lA`hGAffiA9ck9T*-_BQXzl6z@NLfiE~|2hHgtmxWeN$#FgG5puV<^lD1Fj2tyu$5-IQ z^I4LTh|`^(j?W5KV@zOM2YKMlG@3YQr114!0-Pi2^a{X;9i|?{jJ2-lJQPEJW}p+s zw{6h5EHKkGJ31NR8WtX`4h#_QhVW@8aB1X81Rx<}`;WO?6WuJpz{(p@A^PHC7sEQV zq^n_d$V&D<$tmz^+-x;9=|!?(@rm#V$y!vK3*DregaOnEeRmiK|UI!n+arYP^A9SMj#{hg#oqVmjmFA%0jY67?W7bPbGjD-#)811ZY2l!IOwPy(GnE&f89t5BmyD&@}* z&REU6f@wm$7;rw!dgQ*Qu!rDl;IYD0ctxr>BLAe?)OmKDu(n5$=EE~47FvxK75aY| z6cINTE>^EEYJXJgiX!^Dl z1wPu{u`Y0aa;^xyy3_(JW)B8Hm{*j~;->2qIx~{WuktNAvSUF9kQP#e@9}<8h-@|F zdwI+=jGaU?>tj&d)ISh6smbj>FyHyAH!pd_%aL&xF%d2COrpC1k2w*^I;bs6q)_HY zR1B8%XBw`p*3f6x5xzibhK!+Pf3OO~)70L2oYvVOkx8{`ve z0&kS`)>n*&VED@*pHjaI1Fz}2YzrA+6DGs89!B_l#P069q#Y&GEB?{BQq=6;S!kOh zZ7=8~mSpRd3$YbYXzFW#K>`cnRB}RnZ9+p_#2>a_B4f`MPD14WB>#H49*@Z?x{y^z zvSqlwn5l<38fgIGV~bFJ@xwaStezC(eM)ND<3UkIW#jl_*#chi4;iy->Is8zGL0yN zyhMW~b|0?XkBbKzkrt)I`macGJk3$eFF992Lkr}mQvp6v`l3;&M6%hwH(m3@W;~ZG z3?0ua@NIV)*r$^)NX&KT2a*rGlZtMIrCtjps!Wp)d6S=XIkp6p)43ZgqoGe#qUU|) zMdFUz;0=fUS-?KK=a=^ zxE0a|{5!5WGt2LI_4}JNh*#tcj(hUquCE}-Q<_?+ z=L8=paSDNd=f-?#f1if}!x?Ez2c&AkBCO!W$A%U^k9OEE_EV zx-3NAdGwSq>I%UIHz-zK8{fm9r+^fxT)&CLvb=`+-zEj{h-4%D3TdBgb8D-7l$w&*L? z!zndYKxs69%JIdN+$2g^ceU9tKR>~X^2iX}#pk73|3}nWM^(9fUtdx}q)WP_TaYg4 zF6j_CG)Efg?(Xgql`cWLI~1g)5v050-RIu#{k>!GpE?|z^E`X6HP@VSpTnslL;3)uk_wDV47 zZY%FRuZJYyLIb^d5`oXd#0;DUJR>0_&k{671r8d(AI3os_^PN zxPB_GLVA|Itt!gHfS7t+31S9jCDWu~o|_OWeMK56#+ldhawHEN`yP`Sav|CbGo9X- zzv;n9u>rI3?4!Btk4KstFXA8Y^`Job9OS>wF*(KojZGMsMZ#vr&adU@Y8>V9bO2>j z3RnWge6Zf%NMv#bn@-^P6RS|i;XIQ~J?(rzG)p+W6d~~X0GM zY~Uuu^+Y^6stu!v`2=FsXgNr3&%=U_F914Y17s^205Smn8+s12?6c;z2M<7})wqN7Etjx<)%YHJtl35#(l+K~O~2AFjGg_xlCzOHP@$u147*YuJ*s zhX%VWjr(BBzN_lzt!2sT9HophD~nvl{;vD<{i|h)F-w!9P}!K$zS}uvBh$QLu7}Z& zK?r!OQ1Kq~-$D~diR(ijPxxcVI9ArVSH<4&rFC+}ptpzidLi$T;-Wky>*^AIe2#v3 zx6z#beMDgHX+z@qk4eu|vaWQN__=)`3*Y5D zB=vFFZ~hH_c9UGvYB8@k>6WpE8buFRfRPbi&@)UrX~Y9fvMSaQOCc)g9f+sd=W&@3 zf2w=z12_Y#yQm9wt#ljQUqERF$wg3X{#CcLigdeI8%x%F#qF9r!ZEF1{az|b3e9vJ zT*7ooRO4w0h?MX%t6MP~QQC4l+n`#UM=1#F6cXiVxa@A^XLd9HM_}V@0q#(!V{|TT zYzWI*lqHt%Rzt{aJDWayPObQIW4kXQpoz>!6ofD%>dot zR!H`xH?5Feyd@svqLYxD)|qIey#e)dzbl2?ivM&3!_O~aF7K`Q0J;2@lpthF#@8>z zjFzVuopuGg=nl}x?(Rb@GW(T06*cR$VHJ&Sw=9b3fL6&qeg5CJ(qfc1DAAARuh>O- zBmTaKA0j}MFDi|{ia?i>6lc+E$;D_FojaV?T6t0EA-yYF$zW;P(SRj(F-%WN8{F>Z(hkQ&l@h zHcQl`o@$8vga|?B(RAND!LazDai92JK|`^5vhGw-P*S3vHtm=1kzkEp%u7!34S|2=R62?Xn+_|K1nv>2 z7~^fJc^be$P`JcxK9Uv`d<*D2p1{Eu!JqRy@*LDEr^=%D&WFGzcJ6wx_;-`Q>Ceb9 z@IGMI8zQd25`e;o>lx&H_V1F!euIb94$Sq`c45)~?0%Sc<7B$R&}R7*7#=)edmc~I zV8eY7vUt)9xPS)zu@*(CbngigV66~C6Xttt->Bwv*OH)!l{MqnV|AglvDwIFYPRTv7^tz_(%;}u zwyN7!0?_vqQQ+lBwI6p$Gl31)jUTD@X^m&u+yht(=?O_8iIK*dXTe`%iy}8`)UJjUmzwQqE#%a;k4RGFG5UFX{{RJtF zIv2mBD;=<0T(ermYb5iP)%(^i8c=onI$MjX*(UpHkXXTrbl@h}-`W8gnVQPxys;^u zD?uM$mLOa`uGb!XIqW$(Y=1QJxIADz?mF%{%~`iWyekbTokHn8_1T`tZ)ixN*ojgb z9y-^<%0i#H0OaeQ4^Nkl@N9Z5L@KQ@RZYu)<-j#+L+Yw_lAV!(B;@|mbM*}fsX&#e zME52^OR&l`%>@3BwkVjM?qOLj`aqkd~Z!eze$$~-Wk$yKN!-k6S))L2EG09 zjd=M7!#ba%?a-hv4=Q!6czV=@XP?E~rx(NvJ-f3MR8O?VW@Fm9+Y-;YzsvNzT#@Ll z?8U)p`yA6d5^3MyPIt|2)9TT8Xp2C+yUX2{dzmsii`n)xGTn~rAv#ai?~`-icN=qC z_R7iEI~KNfvjye~eQiOto3G8ijK4;i4!nzJ+!M91y)?hB%t2UqROqQ@#c^2d8X=I9 z!z?Yd4-6{HX!O}b*aChR7FdYqQ9RQVv3J0|^hO_?xk-}m%FfHIo`w?ES^kjt0Bks) zfklDgSbTL1TqshkpTwAYWwBF0No^f$9CQtg70R$i4CZFVkHc;dW`CIFMzUedai3C? zk-|q9twh|XxK*w;G*Xc~Dk|;=)UB!^@}jXb=rU)DITmA9Vc&= zWf)L|TS-(F7`$*0MZ{fW6w6Aj!hE2fz&?65EmYV^=OrmI?kLn;&b5z^N~ZuzLnQI3 zf`{iMr0N~s*kUY1xx=C&ekA>x4J(d#KdAQBADf}Tp*L!VNSun6W|13BD($7JA4inx zh+lvw0yQU1%~4c9JGV%n*vNLdd7mRPRWsL;zS0Bk0C6-`%wx)N`pJp0$->|* zats|-P3P14~Li&q6g z>6b7m3L{8TB5ng5d@J3K6-Am5NfyAT5P`!^D|Qw)!2%-Jlc1}e)uVP_9nT(Hv7^}dmZK3( zU500^L(cHhUWp8#99J8Ws& zYp|D5UnTqo3Dqcdb#6@3O?Ja`xo%fUP(p(H+j*0L8eSwI?L^?b^ey&-o$biP3V7(b zl*HUIKrCeQy+8jZN)x5auB3Qt1bc7YDD}_eQAfw>R#d!&OFY32AuTqfW0fNXir&#tgINd@`3xS zVa@?tqX;$kDBR&C5Umw_3W3sd;dTp!RylQf#F_4g>OF(x^ar%L0$<=TFf7Db{Xy*C z1jS8s%@$k?`-RXoaRpeF_R4aiW12DVgLvcfC*1mtZRzD=zfsMJ8m-BKwDFGfBIg7puG! zZ-60r6DE+t1?qrlgggL3F@o%%t4%L;*u%!0*Jrk%x+o8a8KDhkZj zAgXv1K>_@%Qw=aRar#Z3ox>u^Gi=JW+4pdGG8AheL&BGoli%enTaK!&C^9a>t(c|u zoqKI2wy|`{P*KzI!80c&G%AkS7sEGM!3Zso$i>ip547&-Suj~c%mc0 z%`@N(W-=z`$VeMs&Anm*Hm5A}eUr!BC=M|RwLje_9t-1hO%t*`M5n1luzDvItPgXg z96uRL6j~DvX@$>H4`qLyUSV2?*bGGKe-C?Uvqvrdb5_36tw zAQ0?B3{x54ha0Hy@WB}CPNeN%1lFmEr9 z<=v?`2BNLVK!A+fCkDYaf#8L&1HROr1wp-!IzfTRh|f@PoFm*=_nZ`XALS>fAuQ`A zclxOKWios8e14T3Y}ez2+G>s&F*r;`jWYQ%9K{_Lps13P%YuzLM)XBVwb2}@Z>auI zP18&ycIpF{gpGC=C%s_CGwU)XgI?Xi4=@_ZNVeeXNk_yvU@_H&6CmTt;3t62*Hs66 zqCk8HPZ@SQ=Wogf-~jq8ZfiZ^oXf+mJ^HVbPq%9P2M<^x2hN?I4g7gYB<2ac4N&t- zAi3?QS%9W6QGuV zd?fM4*dWs${%rtPhKh;u0h+)jsQ!~-@!+vPVKjN&dBqDVy%EG?>1yD`bEe58k0>}Q_6<8z+*VplS|uK- z!o(UbfVX1DG) z($hyBOu9)x-WPU_7Uy+#54oY5MXurQ5dOs$&+j(TpG)Xq+~;Vw8{ry>tx zzJ^^q6cmfa8zX)U8s77>SD9}8DqGI{F3#BGHZWq`@os?2;!$1A)IS{q=1yi^+Wkfp z5!4~m(ilLa^MY>8Vf>-GGVBy|eC@1mLwir)3EB7vfS^&&tA&@PgeVe8A-s^9T#RuJ zw{3ddB>=Nxxq}%Fw2F!#Z0=a+2oDiu=vSrjGOumrK+7jg$0(Tpi6kq$HU;5w8@c3u zyzY%sCRIMm-A7tTWud>fl$_Ilp9-Y}4^Ij1^2_{@P5TTI6>+!lulBhjc_W%Bs^YV* zCHuL@iOX^_n~Nz)UEGlYq0Z*`XTz34Nr}+QC@VWKQVVLi#HZ6m@xi_uNzz&WSdq(^^5S*M@WbpGStI>qNj9 z8~86o;z9I>Z{jDi-HF?ZP&51!l!J=AXo|L6VkC%((-@$|Eola3xqXBrzag?LD_$PuAd|R&ZLFB?wVZFL=~Q8xF)$<`F!9S zVs)utx$|1&NXX4&9-hRXvF7lYi;7jCT^E7zZ|B<+Kvynj^fRk+20c#4x7rsjuxib@%X#~CVm%DC`9MN;N<>RS&S~-cm_i$w#*P?&vL_mOO=n}J0MmQ zIC_`|?j;zxLbqZIMi^2C3QFnt47j^NB*$oF3&`}FFb6rz8X|<77IxbP?2u5{{B_v% z5$3Lk(K`C>*lu<}Xm^9I8{}m6$(%+wbFe=n%=q?T%ecv#^L=Q4xcPbs?3NxdtGPvh zV|WbuQJV$JW=_|CpG8DMzp4=4a8@^+W}4>x{wY0V+|=4DKd8sTT#0fz@u4)p`#sd6 zkJGE8PC=1`HlMmxU_omT?TekdjERablUhO0YwIZnW?81eS^&O+jd;~&n5l37ffhx8 z!`U6<#jCKJ98iOK0;79OD%;*-(oD{09tNEoveK$h`9LV3Gg8C*jA@ z;Cll6b-%7vsiOZqAwcsb>A7hIs_sKt(4Ee))KOh=8TJ|FlM|;t&XVs1=4;GsrNqY} zl88fCB!gY|K=RjA9e%kxQ+fH_`7e%3wCmy0?^}QmYt{4*TLAH@(nBf@LVrHPF`9l_ z*+zO#Zy>Z8eWBuW0d=-Od!p?rNbph)yKvO5HLk}vRjdOMB#j-HA##2Jsb4;>+>a zVXTCO!DinqM-?t}H0ZJC-|)rC4k+XJvMHIv)XINX-KKI3E%Mg#j*m*I z{Dym*cwJ&>HP4AtL&F40dK^2HJhPgC&){p8hZ>-9&rWHAl4$2U3tLDQudFjC{AO3ncVI&`C$xkb&uV z6F1Fw;2m2Me@X@k-lb(xv0bl)>2=&Vj_)6hz0coP>eXATEiZsMryXz_&b1LvJd%U( zW9cC!Q9SNeU0#=iWXGp=BZpr6C2$XuO@_!8^uxEOT?7P~7wy;zNe%XIBf$iH@UwwD zMbh!H)!#}c(>21XezU!+(_J3>)VO+$uGq0@N4;1A%BWuxaJPO>g=? zC$&G`FA#uIu^@_Q^o{G?b>`jimh0U8_=i)J`%3qS3)<8boo}4btRQQVqZN_JXfBs>L%a&RttV9 z70_GF)bXe8g<{h{^Ywhyv@gtn%dR2Lf@yVj4(f1GhTOzTn^A08FyucJY+HfN;!ISR@RRzt{^#8gj@MR&EzQIc`H=m~> z#`w|rp|8eZA&NSmLOO}zWpPAm3XXIhyKX_5W~Gjb9`Ecp+EKAWO7hLGOoi+(O2v-X z8Gl@8YDm=Xft=fr3;tpq9&jt2a3i4CLbE!WaR0`4kpL`3n%(sL^<3H(QmDKc|5d zU?eCBtzNnE3iY%r3q#Rz#22cJ|#Z^KxgC7Eb7H6DUl8R{L!LP(S{;v_aWo-1cx| zL&8A)1fQd1B}B8k&Ph?Qv+f%m-mEbr(-O0Mo45x3zo$r&W=CU!L0kp&m%ZjKo+ zVAWFV1H>F{vKQ#y96|Z1moM_{vL8IeYT)4fT!($2U8X|?44g190pm`+X$-$~4p_2F z`kN4*0uckN95?&(5ttm$?VS%eVPS^NK=Lm47iP@Wfu&InmgdFCV{{0VRaq`}zyQWI zmy&5`mr zl2l8WCY$z~`Bx%h)^Dw-e=$$<1l$|_S&oKYcr|h1zuBoB68&!Tr9%)%|IU6ISK@3U-aJPyYftC)RgHxDiOZ931ZhQ^hw zD5&67;2n&H4*}Fc-UaPJ5fn?{j7tPVVGBJYU^~y8%eKzou`%bqrjau3X#w;0lH`3g z(B&2ZsY`j4JQ6>~0$3txKMg3WKB@Me$P=G_{?drg0+1AINC7T^H!x$w8T8r}4gpGa zz%w*#8Y^smOT#VZx;Kk`T3E7gIzI|p()RJXP^AR`_t+o?(S?62w!wfe96fbTO1lhA zac?n&lC&6&6*8tiFz;tv#3ATW(4E`V)sdf$U51L#f=B!2G=zFuj~=r8W_RgA$L7cB zErtH(uGu7HFryN($$q*iL-WUOu3GKk`qEC03ZM3sp-++(E^HRp^HVz6*{@?>b~5DJ zmt?gDuwY1fZq|N_M^FaVr9b?AGR*;51dAc) zc6iDhdF__63cI`k>M)i4$%82g;Bibk#Sh1r9>2vM%_x_?)h)t4=_82IR%e{OmF zr7>+pA6&ICsYn8yf3J3%6@Z9jwai&=w9y6L5?vE|{9uM;EH_1s*)veE57f1Q`L>q9 zryMb+Ie=5o0zB{&pbc5*#mJ8EQsR9=KkJ1}l{VjcueK{gebU!RRSVuq znYQyvuvCP+R@nxlfo!(Y*L`0&e`0h(Iv2{>?=5542aFHt){QFED2YvEx=9JPo|5;@ z0bRw2FMynxY{gI9jYu`yewUR$)?~Td)(VYCn3sHEL3721ivPW<+3(Xlw)Q{&{#-S)({?JP;{4-XnOawL-nsj3qpPr=I9)Fpe2kNCzb7%C97 zH0ujH>ubQE$m$YaU3JwsV+xsqI#cYAMptvwC z7sHbZr#L_YNabp&xXO)Z6x}K{eWo#^D81ntUOZ}>o zg}n3OBq}%Tobku^Xhinpp|`0A(Aao{1yZ_X=BX4kvoG>ZKk>^|W78yAzGxbvK0V+PczVD)azc^wVtQcU!dKD1=->dlRW3z ze?KWgfU&_W9|L$p|2A1TA$toUCHJ{j7P8xLtaNBbgKK6*YUQoPw<2$fG$MT(s#tm< zPI{D4nn{s-MhX`Tr=HUya0xiQ@^YIeJew=7{qp+}*p9U%yX3T2FWwAyY zkH7cIJ}RK%m)|O$bqZ(aWo(_})U?ebXpzGluA@J-)X|YN(?@}dnr>K<0r-gA#!m2e zd(}N*cnAF7I9WJP=tjuJG|v_uI=~o{4a_>KEBkBIH1Oz%Dpc8 zH$`W%5IZ72{PamF({i2$XQ*w45?ozRdSQe`@WZ&5=eAQu~pG)@3R4cG4_gDeXbQNt!9f)V5wUr1EWm$&wr1jV8SyC zFNM&w3wh~o5gPqkF83!a`rixoCa<0}t!&F|u9@a0AfRdT_`^YEAi3KprK0?KYJ}NW^N-VS5GE_Q!N7~B=v@jXgX}9# zXyX-5BTyZR3%s8Pq_&FclODH##P3}CJr3@)D5wH$xVw3j{b#Ugq>C0+L|>PJQu`Sx zAIFhPy{kIFlhsQ)oWP>j+)HIxoX`7-t8)ZVv>W(wbV zvW#Ep5FZ_T8Idj%qidJ=s9yMd$8X*gazKTrfykkFjf`vz0H?OHwB`@#2?5^lH~~_3p!~!OCPlXU&6!fno8jH!><_O zx6IrXxzar+@XhT1?fV#SpwNFglFEL4&FtAAyr#5}w?0o-ARIgMNs9_(&sa<5kCSbkNmLh zEe9e#Na^x7fmFr6f@|z*cjz$qhWFd?r3Q%^@`Qn(kQl6JU`5WB^2;4+_?C826%;W8 z3?NGXT{?_c9Dlw-UKk-*WVrf4oJe&loTdK$I6x$xzLfv0_SxSsC9%t^jOAXE>+HVQ zTDV_ja80tkYwjW|h1Yq~o~%)a#m6@8{THZaOZQarMsL0qx%RH()bN6}eoV0S zYg3iR#z|TJ0aXCK@(m8h>tK+Q0xTX70`9wMZM|?z#5Vz0K%D;O9|j;-mQ`|Uj&K#i z6@unRsy$x7fLgtzywe$3V))_34|$9gW_jL;cE^9;TO`67>uOGZISJhf$UJX?ZP-O` zWO9-+>+|GznMKCX!%JWF&j$6Szj|xFglqdDWo!BGR1)C`VzsDCtygiHG<}FF&lqH*boB6gkWcBeh zbz_#sUhR}_Bx8GO4eRgpj{Rpyo7=*evDt7825QA1IWlfR9C=CpgD=g^O3uv6FULZw zavH+-JX{|Z`S@4-5T@vbo_5-`fy_sZ)0XlaKN%&{@U2^+)pk&S#4Q*J zyiKXN)=Thv(=b$Ls(34()KU~-mDM91j}AmXMo=jaIW!Z{^?*LN%szHoaY8cKqL{L) z48=TM)lE(7Yfx6FftLQqoKrFc>c>yAmKWI(mk|kw|FsKvECXf2suD)iP};6x z0c@<@T`ilJuvX#V_F2jej~?t=E!GU@GJm2AQE~kcH{Ps3dD-6osK?U$BEAR7IsU5V z0N2n0t5-gJYEhv`i#h)1CSAYue6ug%^}faFs}@PfmieF>){*uDm$6ZXd-KTM0p0cP zp(q{dKqCco-eB^9fbLs9y^$?wXnrtbN6SPJnFx1d#{<`{0p*A~UK%ltPLb{J@4pBP zN~WI-4<|EQJZb?kQzC^$_x*ApyGQg3o+5C1!Mc2ySDgU~9q|ry3UV--h%Vq_m3?DN zRiz$OoOJBGQc*)A_`lzrltY2se4eg^CzY1Lupmpb(m(|q!OZs;By8tj>f?UW4I|B4 zUP;+$m$W>d%f4^bCe2l#H5G{;xv@2AD|H4-SfNs1cz6RW*?#%n{SLbrwjeovcs*E` zSZyv$i?&wHK00J+eCU|`W` zm`kuuEMy4I1ai@2#3>$^bd;2{F(7%tav~8&z-1T*L#SO+E}fFY`?mC1TpM6PeuG3% zo7M_I5mbQR`lbi;6t+*Uz%U4n$w1+0Iz83+Ev6LrAwC_Ib5O}YQeMIXM~Mv;Ri{s> zRWYr&JRUn8>(0k`s^9E!DSs?B(RhjxrT2875e5di&D^#SwfCPcm2s^H*6gldXURIM zB!r#4C5f1_qEWAi*tpsD=zkgi>r_I@RztUA+DtA;r~Uo?$CCj;!r|A$CG<>72&aEV zd7)8O=#qo1H)$6YLFVgwt1E$+|G+(J_wkFd{PH3wV<#eJ+dljjxCVS$sD7h;e!aa! zQvX;u{16GRZ5)v5g-aMH*kL*ihy>4j6fz@W-r(1=S2V7n!B8gwJ)Q*AOR?P02rFL@ zsdI=|xEA~OWtD%f+Eu5AGgKrzT<23l2Vu}}(Lw#JQUCeO(zk_l!Xxh0=igcp_>sbr zQFvXZb4!vq%)27YtBa3@x~=S%`lj(wmc|89vgalFinnX1q4Mf)u6L-TzlYtONiiT$ zPM%7U#os<<4nQodRS4ZF7 z21;fas}v02R{Z(efvj$0cnUIddX?@yr(h}6;Klxe8StjoIIK(WO68(Ch=hT5Vh(;b z18QuaZ&&|6tCoJ%1sI$()N*-oL~UEn7nb}^Id*CWMKQH> zdr1**_y^l(vySkuycUUNF2%FQ2@);-!T77)TL;s9hCDY zZ%n0JOJO%&x>?XT11l(hTzp!xKzoW937joFO<*&i8So2<+i}wn*kt#!{D6W6U-9hV z^S=+X5hX5#?Yz#Uhb&G59}vS5+Q?L@8~CU?MLyruqvC4T@t)KVEZ-lZde~_#r{Zds z()}#>Bpd!S;ZUq+*}CV}1zkc*U{GfpQTMr2TbubLPSe(}+KuK-?oH!E3b}w##pa2+ zBBmuKhac(^4;S^+grG3=KLMj%1%N65I2=o?uIiXhMBkZSp0Jh`T$F7$od z*e9;(t}#|Bva$o(|Ag$pF$fxlp9n1M8EIhZW+Bgz$V-K_t^Zm?O!`@)QpU_K1nPK_ zAnCPzimRw-`SWd&x%#HBQ>^bJ!Q5Hlz)t08;913EN`@xAZfUfQ=xsAc*Qn>OKh6Vhc8meoBC)a~n_!jVVC|;HiNr2{B zjPj*NB)%Bk{h07z7^1L65Gn`6(34+v=gv6$`4HXs6z>s-awe3Zs~ZCKZ)UnR*b zA01SrCmv^RwHxl+y`+Odag9)_tCfGQk=DpOr zcNE-rw~Ed35=eXaQpfqdR{wtAC+v8qduH?YsQ76tgojTf@mblTt?T1Icv4W^*6*;_ ze|eQ6ziGYUp3)krBM{j36P>hJSFen7#9y9) zZwb0kZx&?O|L3k#^}=beMoyXHQUK&AZo^eyN=^-KgsQ7*G+Y`xz5cf>G^yDWnl zuP6CuhaVu>ZTzkd+D?&xw=Io7MEDc4;?kU!T!p~ z=FyGudH_6?taGq|6PLvpX=Xj>oB-V{P zZyFukm)Y>V@(+PFw}6vak7UyiR4WTl{!&`1N>8+DBO1LbEj6zH|6#);q=31_#WbK` z%Q~oiaU=fw{c_dOHa4YnY|mC5tFXZ{M|<4i7fF|({*CnQq-T^k{o9gc|@R#&^Cl&K4?$ z<7>#I;%lEhqI(r`S8XFhO<~BGpZ9CG zKNZZjmOWzW<#i0CI>-SyI*B13EYHK*9|x=#*#4k0*$AQs-^WW|M}U>mW6p!<0PX_D z6Um#zRB*pXY=Cww+EX~}46?iKLXNuY@h9D4qqHz40kU#uoxYUkAy|qO7OhwG)YO09fN&w!ZJq z*MAi{>Og34vt#Nv*+ZYfxU6$d?RFwL*AWUv;!ST=>+GT?L14X4hX=Y_M#<(FZ=3I{dYmA~H)IMf)T)y(8!uo0G3krtVHmC5rCc%TP!@iQ=CVC{3AMo%G6a6Vy z-l5K6Le~5co>x&rd=SL<0U<38=u`vqYqZQ=C;UAIEW}4> z>M?W=vND0zCCf$mC%E-@H>J9x0U(XzehZVG7N{k+AV(+*hXHU9K&+8+~fl&78h?GAMVTPg=+B!ieBQj=Dndfj_jJl&*gtT0-vA9 zzLoPG6}GpkpYM~H4G|mznXn@6jjhp4dN5aXD|rV7 zf!^lAztjJ!e|KKICgfb5H!-eyZpw=dSLFOf11H2L((?y!+A+hR9Dw@vNp<}j8GrZyFbr`}L>Do)`W0O#_m*HJomJlVGlWBdsITnkW$aOdsFLQHy zqdOr$S91g~6`5M~R1!1!v^>d|!{d?+SH>y%zl4t$&OfLXH80mrS@ zC_Sqjbl1|;ZrpTynJv+V_<>sdXzV#;LE{rOX;r>2j;&n1{kSVNqQ*PITiO@gNOzrO z9JWu9BI#9fY%SW}IV7TFQLq@_^`oPtn4n7?aWo$Z!*;8t-_MRrus5kVwnGRMzju23 zWe|_F`C6a))AnxxfjS~%4PM?Pbp7N z9guNXZkn(Ai{s&@eJtXGbx`<|6Z>IcdPL=d6Vi`KA+mUrC}UoZ+$lmi{oW*iFE(3w zHuN{<8gUmEFTotX3HEpw@j7IRT12fQ`Oty@0Rz(_XvGbs=6grUAFxfLhMEiBk=ov9 zkn{rmayEy>@cXL|fSD#GO4Ya$dfLP34a#1e0~tiV0sB8hH&TBA8+3qxLfJX@=`$iq zK<2FLM4b-5NA+jy5o?R3L=;DUh}IczNBwXleAT2;mYnO(`tvs5js|VAec+jeFBY^( z8ii{k=@)*NFgG)`xSPt$Qk;+{Zy~u5;m;?dnB6xyfJ*IIerhQGzLnx4lK6>=@Oe_U zp*Tf2VOyYQ0JFU$C!~Q9{A;*Z=37Cr#NPgTxH`x7hl>3{7!B#^;9&$Q+JHBj#O-e- zdUx7kB6Tnk{=vUBq$35ntTGogiw{i}xwBij|4-<^BSxdri_OuAQ3*bI3F*`=vJ@&&GPu4cF;@(U2U+=%D&JCX(xBswh!KOnvcL#u* z@q1l9*c_2TPo5J9!&u2h%(Lo-Fs7=iGZ=dzouit^a3T|#&r_=%8!;AHdH@t25Gdpi z)FT&3BD9n2Tm6QYM3M8vI@~>=skzLjPTmRe zQNfpr#7i7wy%|J$^HTO)9#!AgnRnlH60NP%*;?%HZxzzsau@{cGf2<3HGYf>_5}IS z9=v_*Zy>T`Tl<-@^cFZA_3}k+tHlX;;9t&_y7hr^)`Qxv7+x1L4e?Q*^cj67xyc~i zd?*!)|4~$&D=b)>FN6{!s`W~oa!9QMUz|&ggy^pDJ`P`TbzYJZ1shR<1t}k^M%bg>g)&eoPRb9)LCgPY&Eh4m?u=- zfs44V6Zd8Tuo-FJ+P7Y{6GoEw68KPaIMLKhaPC_0MlCZjsi9m zHp8@hz+H>YFvNa-1T;V;B);GCcU~eXDgSqDB)FIE6uMi0l5Uv+Er5H z4$E;!l7@EH8s**BUy2nYxf7$8cqTb>vNJ?Y1tcH-_;Nau~vy_@{cUUMQ zJ`T1#=+g*KT_UD%IOOmor}E0oS;FA&DiBr|CC$T}7Jo99D*3wqEl#yHZUzW^s67Mu zFvGicdZi4AgW;{2UJwU|Dzf)fyk<{j$GgeEYZ2G+-EOD) zcaU%A0!qmpJu~1gzuXI_|j(HW5SaMTOP|{)})JdH2ul2DZ3hN54>BU5tr;93LJ6s zUDXsS+ZrAI-Uc5)mVN?@zT>MgvJumUIFeSIP^tQnNf%WOdccC)XYdy_Q6E-a8wX>XiLf9Dg0{YEsDQ_ktcZX%b^;y1{696Ex?%I5PrFc zP#TYg=r7nn)eMKfmuCQ{J=6AyX0aKT_$Sc}SCh^9fij)253v4J0!MHEnM)7q$_^F` z{K;NB%63&NlI5IhHhInOJ5UJg>59xZrLX%^^}<6W>P3A`$)`jyQLmBw)n86&&InNx zs#K4We3`T_b%we$((*Y4eMw$d+NG6eNlU<``#{N|F~Y$v-XX!!{lb4Onr)!(CHDnz z#;EM%gi4{oMaWiDaB}60Xmdeg1$G$Hxh-Ne8Ve7pSxjb5!Aq{c8fR<7<>GmM@l7M}SbM(+&`MKzwJ&dPoy05J=^I<_!b6Rz@<(kX$Q!qK&fqXjmpfvGd?b!G`ZZgK@hg zaG z>Sl5(a`ydCIUYkd)--F0;xShrK^Hx%xGY=6)dZ{$Sp+;@yy!M4=n^~l+6Gj^sr}lS z=}@{iGnjKdBhF!jJ>1%V+HzrAf&u-yA+|#T%w@r0M;c>cE=l_!GI~9JNI<DYc@$M9_8Q$tBMJMnfm;^sN5FC*WQ)fG!*Mj53Qj31(oXR1K%uD@xP2csd z4o>{JXA}pDE#CiQ>MY!%?A9(0NDL(nBHgJVNJ%3g-6`EIAcAxZASopvol?@>4bmmj z-6$>15Z|8nocCPcAE4JY!!!H2_qx~mtz#^F47?R)RQVtER6WBWNH_qu0y^+@O$+-@ z5Jvm#i{8d0Jb+c#QgKAUVI5i!G=shCeEzF z=`(@DbGn>@!wrc#cD&sKdqO}LY8hb8WS4fjabyO$4ohSDqqM3$R`NttKZ2Yriin32 zKe_0&s>Va@Fi*&xidL`D+_BDLG5qdtNMm2avb4_x-N#rz*adx*L_~bTYrvVm^@| zy=2=CExA@QzdVwL^gkpH1rYMJHiE^oG%Qc#v`u;o6@Dv;3|$e5jZWY_AfJ?$NvoyB zARUD%0$1kWU+*wgZvn7+Kttvwevg}XaW#JUMu5Fui4<)xRohBJSftDwu}%iJzt=#~ z)!oAuN-`r7W?0Bjuzq+UecU70$MKv_zwg*33hEl;Oc8A$tHLOXlr?19g97uMH3<=T z_KMcT3l5&NL&xVZk3btK6k}KHiL(Gs<78yx`}Bm>6z%a#c#S$71xfAc-$qmUbqF4r9}Vx`q6BH%t4KBb-TIAx0F0&^DjMsJ4IO8Gfa3Te#cpc(t z^%I+H!r}wAaH@g_4kRN(-B4;;S|LABk1{%g*8!)FvF+wVD`s5j&4ZeI6u2@$`RUG? z7Sn06E&{O90>pGk`K?Jk#kMuD!_6k4Ils_4&jz(?#TtbS$*xx|09d!YhEVYXttobZ%PQ%7@GL zhXD|7c7W*#j~4376_PkRmsi$X6KOlQ|D?H$I-@Qc0@Qkk7@fIh8ZTB~d@|C>Xwu2+WA@!w z3Q}3zqFr~Xx=i4<{Dk`i@JER?Z8OYH&?7hwIs0;k?v_Lp7Y=GFRwYbPa427{_hk+9(7%f%?E$- z$qiFGk_3dSB_rk(S1R-i@ueOb%d5K?7lIzmpnBk37Bm8YyjD16IvHcolB8!$<|L&= z|KWw$a3C^tCGwP$IXvOq5QEohl*iE$WB zag_4CQZa{p8n60*w2-!q77;IB=^kw?TCpHA*M6=V=8aXmi91=Apn{q~t0tT)6>Hx) zs3E2$*p-JV$$`A$j*-oXB=W~(jnd=;*o|IT(Gw1U$GHrkjsAQuw$JX7L>6xw)BKQd zK9<76CWrM7#HS~1a{*cfH0*pS+zL$sKqloxBEL*MznDAT`i%tM~=hG_xB;>Q(WBfLzn$9b>H(l8AJZ>8B>LJ&#Rout6#+|0k-tA|M;pN+Kaf1+ws)C2Tjkg zN7_F~ng3>wHA>7ky6|B+4PDF$kwGCxQY$2hhwo=7eN)kGYZW%l>^t-FDL8=n;F7lB zh{Jcz195#CtXT+>7@~-fNH2?sGjZ3urUeO0zCrRbf#dpBga~a16$s~`Tb;x`qoDUz z`}UJVgx0tjSv3kJr_#6Yw_ckZ9a^2nl?E z|91;$feCPYEvggfwMdB9RB+cqL-};)bcp8yq|z(+dI zxaoI0K^yolA2H!083Ke=_**5X2$wHQ64U-f*moT`3yQJx)Vu0oXXqD!5~E>VBB&PA zu!BI1r}}hojpf-r1%e;!O$2eVHU|H{ei(YRK@<^;@+3ER@c3)yRi^P>(Fh#vhU~W! z)S!S~+2)U-B{x4`=3?Har@1<11h}ubi_*D&oAt?ao63KGW5V||7C?eg9m9qc?PxFp zx|yf2Cz$$eX$r)%z(!^)EqP+R-S2@MomIsNKOi+H!QB{!Syv?tuivSTVey5PK@)TX zViv&~u;4fhvRnUDJm_QCt_~(x%=o?skrTmEbrDd%At+DN@0U8Zig$oNGjR2}F9&&- z52ziV=c#&L_Pm?98Bl2h+nFlDmjYDJF|mSR?ycaR{cvKUYcA&RkG{@vw+b#4UjdjL z?2KK!L1(ZoUZx8HTTT z4wf%WFa9=}SM1kO#$c{$ILq9~Y}F;$Ne>RsvkP8( zc-$jtZ*ZGKwoU;au`Z^$yD~9k+Ge8$rpcKE=V)pfu{AIRB!Ea8=O5RgOE}xvh6exB z>A~Pni%;S$q?ac0WDmT5?+B$S0N3o7mChx+*A)}5?}qZmJSJVa#qf{0JuKqnWz0iE3v)-`MvRdIMvyVjI@<7Z;qbk=X3hmEP4&5SbSEuqEdz z$(r9F`Fc)`Xw%wdM59!PDK`2F@#hoH%lh-WVj*e3_W080K}S8W*8Pflg-14DF+Yh<-j zHDOZU*%2=9juEwLE*!E4VJxQ8q&(7V6p|yO*wQ_zL^AAm*9Ei-eEA{%MkPTqOLe5a zmn=Clu{l3|%QLwC9t(ccG5vjOpwL~|z$v2)AJ<6Slfoj2Bd#=9~*i^ebr%4ShWH;Q2KB?Mk$p@Z`eSJ(vR?OduJ-5LqjQeOfw_NOhwCDkK=D#&Ha0p7{tdU-fuA{^Pd@ z<4-hSYPPS(T@1X1-SwpW_6Pr3A@oDwD$dL(Ff>w~5x-l06Z&?W1qJtiv(Bf2%jx_j z`?q}^e90jb`Lzpk_G_;N(^>Q65=Ux~NPM%~WIF6(b9~uZIwMZJR8+(UC|QK_EiIbe zo~-${_2<~oMu_6iRiS1p{AHNtDkwwOIxxFWmuQEr_sR`sJ(6C?MDHNDE6ry}q}6lE z5_8meMN2yD5t|TZOjLZ#ZaC!;EFWp+mC9qsI7cJ1djQz08u`p!c|#eGXt{sj37=SB zlFXtY!+;>I)dqw_g&{oJz^HP06}Qedm42Q=1jb%*yaSeavX^wLEvKWHHF90yKP)_; z3CcpewB+rQc6b%akaJ`S@MsjLt`C^ca93x8oUE)x;+w7$Yz!T0Q!|5vKlU&U@s8dE zlra$$qSvDsH>GwzaB^J7&!P3Lb{81SC&+ke*gJveH}z<$LNaMPt>WCMUECy(L402T zB)oGBtybWjaJn_tvF0d<4Ow={cHGT(Jn7V{!Ppv+$!}+M7zt0b<3EV~dyAUoH0+AJ zpg|}4hW%?qk9U`qgz6#w!;)8)N7Btvr%+;r9{uV{Wk0K+=q`7dcL=_yzpYM4l^HWrU9t{%1i3iemrAtcG}_pxM^VWZYSgWy8V;-&F` z*YRe!T=fq-^09+O)QOD9_cPb8nRBh}4gF`gSQq7ZIV4=GsDIEjGz(Q4Ad%%5#W43r z`uA^qLgPbGGeBZ?SM5K$g^HI;1IVL`gMm;Uk zmIN8~IBTq2Wp;*Pd?SyN(0>2}+1+n7=3dOWZwg1Z4wPqE9Wx4^GntC7Fvu^jD9f;Ggxr)g(xhER`6TU?4iZRgd3Mq*;$>JXs z$WOqNViEiIt%{HJXY@LMj9_8$;~1LElU7axcWA z&r&g=M`N4X6Cz&pPw8brM=h}~thImrclJK)RwtsYAvU7;h-k1wnfT!ii-y`04c?gEc(S6e@nNzt200${mPm?77IM>#L zNh>7f7+At~n?nuNi{Zf`9rf*W0#vZ~U=b{hz8M-ZyY&yhI!I-dPn-Z0t7(a!SSr&! zZE9&pEXG;YU$+`7K_a>GP>-B!f3VM$AD6622M$Q{;9_MLh2&oUOA%KrW~aeO0wmU1 z4ChGTaE*;eQ4(?*UG{}J6!ecco1#jLV|}_s@I5S(XgfPF5B6d=)9*{oir8Bg6Gg8g z9gIrQWS_OtcKWi%Vts+u7bq5j>Al}w?Fm5z|HZ**)&gj)p#k;-TZJL=D7-|?GGjBt zxzAe+=1c0Lw5x`SZ_L79>rK#!*%~BOTrK695VC6zz zq)#(nKkagRh6%Jjlfdbt-s|KvMuTTw>!sW=1j-RYGaDWc8%(sRzAvE?BGt80UyGJC zzG5s8v!ZhGq}{0Cx~7S)TR@ z%e7te@q)|`S2tt>cEjUsw*avNk`%l>XjKb~=Wmjkfn^H5cWEQ@7lBVifz-}sO~YG7 zMd$)YjQ;Y%L)chSUXE~V+PjOT+%%5`E7m0?c^s~AKpj@N2BSSUdOR|}{@n0BI1VEi z*eV)Ms2qEQED2kHzt-!vVqg@z%1)NY-b{~oEwLz@$GLa6^RVsF9%4@G~*Bs<-V4PE<6{*H8FJ*vevwPGLL71afz{83M&Ak`m5cCh; zRrE)P~yOZxCQ zwR}h#>cnV*W`xQGP`G3b{jom}H3cf%?(1Nj=zitkgGFye8htbOh;hK6t=?-07Tz+L zCJl8D^_Nd%uY|phRnw*!1J=5^RVg9rNIV25^pbn5Rgj(;Kq1jz9mZlT?5vYQwZo+~ z&=Tml=o^%fUc3YQ=A0-##7K90xA)=H%4Ze5Z+u7VLb6sr?WO&|?0ZC(BEw%lT;h~& z7L_26yW{CJGA@IX#y3+tyF19zKDiYKq%}+#BdK>$osC{Jow06t@7Wb zuP*;?5VnwiYV#i=- z-;+j@E5f&M7<2|@i5`mVdXx_ry{V*`{jl4I$M}Em_LTC8{p}3OGR0R&?b`J(-bj%j z4cO{^@z}f{vZiil=fb%?iYR$8zeA;W8twBq*cR^ykTl{0&NZSh`s9m0!N4yeKL3m2 z5NRHhpPDMU?kDrX?F1Pm)H*h^gc2tVsOd;-D)sx=*n_HeYIP7MpNeBAO!*Mzr!$Q_ z*H7Kij4aTjq>ajXBn-zmL3Z)^@U~7y7|lpc@Jtptn#^8<+Rw}$hO3h~;1CjM-Ms6> zSr+uZaE;!E>Yk|btRn9RVRRA`Z9n(l<*sc zkh@bG2Yom$MZ7aryg>#L@}T}SUz*w1cEOwyyF|3h$Ta+--|}S+-&UH#CFFm&pz-%48G^-5$td6UXdGCopj%k_SfZ;%bnk4H6d%Le-%d+CRF0} zrT={sKT!8p7T6TXb-dJTsjEETZ(aGU)@pjkyfwx0%QM-xrvPgQ_at=61R7-Z@M`^h zEZW;>b4;h2Ae_H$;{5HVm#I(tp4GS)T|FN&^@d-xDE}G;{x{mBjby7U(R$Lgd#_k3 zs|b4?d{)cUnXFos!a7Tr)2vwUI7>pJL5*0S)N{pOme3MdSG;RT6@f)g(CU{3B#$Rt zkp{^d{#hZR8L8ub$BS+b1QH%vrp~zJW*C)CTo)&LZ_MB0nb(VddLM%$4D;W@Ktv=# zmK1robz$3YePfKqHW7l|_Rq$6jL;g33b^4q7r{EtB$g8SnsbE^54=@ zy=D>Ys~J?|&+`1neHS-8+|n;8eTMNjPueNGZ%Ak==K2qQ1YY77Y^Mq;5E|Etj|nmM z`zgzWV)^!q?mm9XT%ryVL)R6!&1?`7RYr6sq7FTgl=wP=4)tn*QuTcYdXVZ+^1xdC zqKW9qUlAZbrLVvM!*+{(*ojNIUvWrQ-NM^&7l8!V3e#)z>X79c) z*pMw=@wtW2iGiCUI^*UWzZeQNovRBpTz8JUKF8)S7>0lyR5-_VW(0jFKJ)y-?0I(j z0X<~(hI~d)D*rA=Bs1Hx8|)zWu&A9%n-0+y%k_^q*p2IX%==@qvYt!^RSXv~g~x6G zdqm+sC5TOT39}h7aHO8}&178KDxo`!YyER*=SOl$_Rw9<8F6$esX1(}F=mha2wF8f z*O#Sm)_?h9&}od`+$$Ny`@zc~)72;Qp`ytW$=sEHeI)W@Yq?C?o~y-gFMKalajk{B z=m`y8c5bBm8Ct)?7@_*nPS%3A>eb3pxnr_bFUxA9Yu*Mt$u<3{O=5 z+$+Jr5#)u;-!c|xDF;_UrvpX#;2Asaq4bgkKu@Q)?+bAMta6AUK@J$Xymow${g?W4 zztf6!Bv^7*U-Xgx~14k|TTq5`6hh*7r7f`;*FT+shMba%PC=+#q zDS6p>5B@2gA4!;U%jIHf^488ejqM$x(QZm5?w;T{E-&ec@068v=Th9|y3aWyEs-6X z9(rTw)VVw%2Mg0ho7x`@J63ct+YO%lsjpBRmO;^GLow=6%r)H3xM3$`Z<1=Ou{z&_ zMivp8zsA+;XcPE27dphxd~stO+paC)_ukwK#7DvdK_WHi3 zIL=@B!>>kPK%lPFZ*RmQqs6A_XQ^4nkBCKnBXINU*U?pCR9d23$d)D3Adf-qYYKf< zUs)nc!y{d?4DdQDcD*`wTY+l6iZBeQ|CeH?XEXBbotdDVc%MaUA1yTxpj2jcg%(`X zX)c=oAQLk7*NFm*XrQI^c&8HQvtZ4SgbbJeRZQc%qGCz5cqcEuA~@6;o^Nyg4He9j zYE_!x_)#3};mm$%+9Jxw!`JuG1MhqBj>=>==|=30s=1aA`+G*{`F%@I=Dd(xg#QI?qyz{ap3%ETTsg(x44^&A$p3rVJ3+E z1Ox=aofPwuo5YZ1!eDItVRXixprMDdZ{A=exNVyVKAfL7UF zv_(-yK+HR*GJudE-ZLB;u%-!*`|;lcPR``hdP1~pKVx6A%}V_w3)f*y{WtY$-))+K zuL8*wC%n_1(4S)wGWIA!u}2WOr zPHRfDzD+#Kh8$J`N9aF;l41tAV#LB>HA)mI)5gS)?z?Xo|-^+00et!F_T{ z&V*yG+K9%;@3?w4u(wyckLD>$ z6Rjp64c1xl`m@oA;7j_=)Q<7?O`-v>Cp+-nnrJAZ-rTy*7+3`wu5EM+cey@nrXhPA zlQ1?MCV3D#vG>>Y?X_j09VQ?}8gBiw0wvUPr}gfs31kq19xON~>AMe`skM7XEY>DN z8DbwG$n+K2_*RExXBRT&{ zRS%%cSrbUS79|+%`Pe#g%7uCBb$<|yF;#Y@zga&OXO( z?;$!CfCs^Pbu7f9Dnzq~`hA9izDPLtIyNES;gUl#4c;*P<)UcxImN3FF>q34+dc4N z>1FSOJyFzevUJwt5O}qAdO6L9On@_+ZeL>H$2VR*g}2<@sCEN{5;?QZ8+_vWz&big z9W<1u=(JaBI;grfG3R7QD?CDd26Gc9kOyQ5Xw*3fMr;8xw^Ml6zTbEq+6Y3&JbihP z7o_S-G6)E5e&qj3_)^;XGO(X=3=5Zpupqzunxx~HnxZU0S>;fYY*GE4f`dyXXp@f6qtzR@Dsb!b+qC_klglEM!++f&rHYBNAu8( z6cFufT^;5gi|2KiM{eCBoJ0-(lPQ;yL-9{TTznTq`2uS*If8gb2r&+lI&Ab455h7rtm#HMuN_+w9=Cd`_PJZQ&cimKDR| zwdCTL=R&tJ^?3a}3~vR?pEhdpz+!ZCtfnkf^WN@5pQh2%wJnk`KS6bc{R6(eDnhldL$*ewb!)ZDAJPSC_mw35RV~z-K*XP*onLl{F={@xSb3@?zDEn zqc?mnv>v?i%CrYU#u-W?Iq&{R0GR~3Z+JWrjbgY;_-!i*CcfEI)n`%A?HPzMg70*k zsof*kMpqu*VY)&<|Bm~VCeg~zmxdWL<1{`!r@hS8lE_%Rgi&nUa|KBB<{)@nhr`qj zC@EWU^3RE zBixdx-J5hurnBXQgVm7vH)Kb0k~K8v8_j%G3v+q?R)36ZRO7BhZ$yGE$nSf)4Zr9W0|#wMhSi%zb--> zMB}ldY96e&rs{>Ikd}9iqOUKh7Pxv~Mhwaw8*TcUeV9_FnKz;J2fD-}8VN%)Rfz)V z5*QY5SY~xE%@+g}qXD*C&&ti_oqtle7?1bWu~_!gY|IHtlUvYp^nPB29tmk4bexw^ zM6A5dJP=q9rP~DCp^q4?kk9b#A$;dIikzjh4ez@2d!zCZJr>e;Rl5Sr8$SWfwgJUl zo0p4PznSaataJxNWHD>#|Gv&|F77DCl!Q^Q90L5CkbEru!k0-U!4Z}&Qy=I~8OP z9L;GBU8uw;#*cg|=vLB7bydzVdJZURj)9J6vF?w2&Z6Nh$f(mvsv9A8J1KT$l{4O2 zGaNasdmH9tG z|NkNRhimNUH@!%ug1I!eYF<0W5T7@1>TVk@x+4x%;r}*R|Cj@9Ge04n*}HcbVtqo5 z@0IA!lpJiU4CVeC(a_FXtmwwtFV2l12?g)!^I*};sgv_6okJW>!mz8@%KMei&+9xh z`lA%%_MAvHOU!&*Rj*arP1u9nGqK2- zv`;J(Eg0UpIB*X2YNA11UQ6GA?l}kl(Q}HmOXq|4R9Vxgi1Z>mH}5dyT(Emx?o=*2 zT~}6h@OH!N84>0#2yGepcSA_Y0c5^vNlW{O@C?t58HTgq^c~2x9kWU6rgr6rUjo=JCa}4t`x^&neVr4j@C(|`?p98>5oMd8s^zH62+J!*=IA+cIyfADmM^SP1$oG86kBD449)^`&R6B zG$fEHNHUerS!^vq7)oD~{WU1=?VX}}%42I@-$$hYu^L7jA%_Gepd<>wYf<1ZW9P7a zWHWvyUz!A08h7b;m=Y{I+=4;X7Xudshe#5FA{&zh%JsUZCLm`_T&tMIVMz>MgN}-! zCQq8Xe342IH?1WnVK=I9@PsD{jH8Ta0Mt1C>?-)~Bg%XHN)&Txn~yYEzPB8|QiV@x^CTX_*^_Z21ma%lk??1zF_0?GP0^E>azdnhfR!0HUi0WCdFo@& zmx)7?VFM%&yguHh<&7J|8LzveFtiz11hThwPy0k&y(8}RHCb#vS_)dgYLh=p$g8UJ z`LJ7)mthC7yyGvRFYcF4xR&i69PYJCWL^j~^#%Vu2v4qZ+9D4-6-(p;N~UEhaeJ7% zX8>)~wTs0ACL9%hd*t`vVp*|G45W_eXU}CP)Pnk`aku*0`~Wk%BsAJ7H~|I8LFc7Z zKc-bLOzNX#EjTJgwK^r(%3MK358Ml;TV)>R4Q`9**L!sCbnAwo%2i7rlpcoUE2hqm zU32#n5FK=L2Kq-jU9c2K`mkG7+=lj{=D~TF*5~B}(FgAANmtE-jeVmb{t80XqM!uA z^bxIZDsFh<&9kq&Wa3gz22L5jx$OlFcaZ%WL<+6^L4m>_j7_JKex#4+MZk9RRdTfl zXXop_4YGwT6Y`XHD9XZXVqR_p+2LNge9$QVA?vFobi6PT_xn} z->U%tN3#EJa#^rqrd{i7c4Q0P%^2mrvNMHz5R!V!CnP2XyOpf!a--dgs%1BvSkctZ z3PrXW>XYNfdCM4e6ndWQ?;zIlFtTgWUPf3nCuDB+MK7NBm1bZRZA3xX?P_x(!gRQZdb9{;LluHf8vidyp4bCLXUS z2*M}~%^gbq!Nc9ns@Mg0jGdbPFl2FJvM23MW0%)3EF__}tt)-BfU5`@yH&s41EkT*-^G{H}l}e|%m&`fBK1h&-p|oq5!$!5a$K_}0hh5>8Rwu>Kco)sXSE zgDs&6DqLqHk1ZmyvsK|W5xGPG-{Z55eHB3X_wu>nUYL{S8u)_foN;%CX4}BK(Q3(G zHmtGwWC=)p0e6h#k=Yhg_5MdxAh3>o%+TaFYt?w;Lwi{y!z>oDs*u^&E{gAcEAViC zKX7jv9n`AaGA)Ecal^4L+&8Hz7})rUkdXSP5w6uD3ku=CfA(F@WdXocREUr>Vb^Yo zBcIt&6KGjTR?BgJPZ}jh)8!bwVRY#E?7c3l`MQ1ChSBMMyK|Au)D0~|T=g@h6uH`w zFD{Q_6^9t+8D+d5p5tS%yRTW`^-V=o%-hVI8QW;sQRz0=M)ja)Zm-=vp5&G9d^B|+ zj6R2Cq4on;cYyWBkN^ia&j4e=EZa2WY)Fhn%J;5Db1rq{uf*juLP(Ss!~~2A6{eR! zQYh7t&U(Z~8AY^Cr$ruG=brqf=xFd(3AL&hP)S!(?bl?3-0ejnG1Rv}BotWZku3;8KGUe4&Geu_=dna5Iv#_nRFqw!H&d`qgd+4l!H19&F|48E- z{jDeXp(di}gE6|%SzkjNm5_nN!FE%Y zB?9fU%q@O`7MdXu$PHB|lzU8wdtv=qmvGx(--*(xAD#9ICzoRHy#S6Mqs?_}cdy2BPH7JY_k&@`}wUZys zc=tY;UyQ1R9}F$|qR^&@gFl;DAn4yxnGgMCttt}1EZpJ&Lo{ec^lv`4tH^z~E;pBo zG4j=#I}#sypYmkox;eJk&%h!mcr?X0JGA*9;xeKe69;sDvXGNnt4qx52+lF~@1i`kasS1G;Y>k=UdspXC2UD z)ah)b^(P>14YYS$4>-#1e}TlY!^$?xSMp_+!?M1IR_II6rN#Mj)=}3@xJz2NFKJ!! zNq24hzP;pVrcwX4SHm=ZFaiQMB}AwV^rQuxBUeH1I+en8sZK6*MfKI62V{t8(DoM5 ztvvyS=AFdi`Hv-qj(rA}xiMLPX|6i@i}ojpt51GP;Wd1@XDCZhlT-Ci6c&Z_XUjXz z(%ik?!1>3qxffJmM6rNQrEpRtl?CpHR){ z1jO{u(A_VUyhEcyWuVu0cBDQn%VOj*NjMGOL-Af@S^kER3+xw? zQWD4tEt8d^+5C1~IjvMdD6j)KqLb*t|b{>_>BJ``p z*eV&zYl%(VnlRLf0|KRnNT^%V?ysjUIA%mWgRR$9-v>ABreHr1BS$Co?oca!V(UkJ zT;f9LQ~E~YmxBv*Qf)zj;|9XuRbBckn}emt5~ShcRUoMr3;iB4PI?gLX+YI7#9&W)m+xAx^Ta z{bQ};RuqYtRxn%EhHiy{)RQS#@E@Zn2Vl-`vA?Z>+;ah?#b;T_;j1{drDiIOb&pOT zR5Bn|vT${ucEl3ZDCW%YM?BUe$|-$EMt;KS`bWdSu|vOU?O0w@ll20L2z3xLW4&5YeL}+kltCoMG=1sWBVzi+2yJ zXX^9~4UJ;!h1;*k-7ve@MZCLL(cMRE1y^QYyN?lx6d#0HpQ5#Qze{$3dZ1S4vY4y> z!pMg%E`9~!vfm{h#Gf}sd_mWjPP=bwU0n7SdUow&?y_V&VUsT88ers_ASN!TuwmHe z%H_iqSymFv0e$Iv8`ht4_#^VT$Qoa{r;#eWfDN6_a!)Q9CH0P|BGx2iYsL|=lglf6 zg`Z2$itg%;c_If?U}TT?wMlY#p?>CX%F5T>4(bbPd%$9Kez?8_O4v_B*nO1STAlkM z%kIznQ0TYzPGlqFI{r6FoXo4k>-h(`5t-A3l-;sl7;P%kf(z$XNQaNDkOTP|gbmS{ ze^%qDsqCDX;zIi(kwhPP2AuitTnL|Iw^_O(zAGPX7h8B9JA{4#qDV~T zS`sH=yz-V|G*T5wUU<6BEK7_e16!re&sydQBX;v+yZW*2*fe30^89)0DMQs#7Ef%> zJ>PKK4P(D@O%?Y%6*;yi)zp6mn({=lIe*xzWB3xPrlU~J@kh^94NI3tMDE>uT5r+Z zeqL~$f^I}na}AFvIRkJ))12+GD>FL`3G{48KY)w*^GTM-7ke`#<=)&vA#hXubL1BD z0en78{C8t=4d&YdQue4W4Tg%CP&Ki9n=VbWo)* zVITIKFTZwP;4u$NbnH%^xJObrA+}|};>smZSDq<4B_DbtDB|Rw-+!OCokC5q`uWux zAm!mqsNx_-O1^M4>}QK)CejWD?n7vpLV&nfKhw9!yr~wmx7f&y)QirP=6`<&+bgj; z-AfJR%gBO^?Auj4DQlG*mfmf$#9w31WM?VHx}U7~KF>5dF+IH|dS zXCwXDs4@0sV6L3CYBzMq_1QGpTBEVp<`75wuiVG*8|yFPL%~22b{Pfe?;AA&=2;i| zP|ej~DZ59SqCr|>~~>;wlWh6T~v&V?Lraqtfxh>CaSE=e0Y;2?Vr2W$&Ivg^N7ny)hAxg zWzRQ%Z-q?e(em+WlZ<~0MiFjBN0}6}>cUvgE|g7uipmrzLH+C<>SOXyG4bpu-@k-N z>4~p{cKm?#PQ)P)CP$MDvn9r~LF{J#n*zBE>f(tg6#*;2SA{)hotFS|-6*3nE=P6N1lB#GT2dV-7!+a@zv0u*i>-ss$bq{_t6Sxziu~ zNrp44a1>f@?^=0~k5C?)Q4&5|j>KadSbnl2`alZeG*wuM0w=xYnTa}B2=Lg>+XgG# z-@rd`snJm@+p*DgLs?T;1=)6af-ZQ?^nJ>{A&UAJ!M~?Pe3p)1s_kw?L4C<#v`^k#=*=nnULoPH!Y7Z=y7+?q=68-?pp4HG(v`B6ENj0;zknVcpZ@;M&28M_ z@Bh}_`4{#hb+Eb@7Z(p$@HT8N#w6rSItOgmb+DN#A6$F@gwnH}5*EzMAUCJs7OT&M z1h+AY{=)7?3*mxLm4bc_ZgE^>aoiLP4gUM=d8utuinnLIy17S%tkQa^dh7GcN?rtK zb`p6ZHVOIH35JO{Zr>NIjQ&&%^6%QJpfTHVR5&227%IOzs$}`|nk>ve?#Tjq!Q6JUH^HPw^~;{c#7Suxd!S&3Ul!@~depQI9=BPtas_FxkejW?{{$ zd&b|u>{IV3=zII1T>YDS-MSlt! zg{?ZTF_)5rkDh&5R+p|XuqfTuOfj69Iq>NE=VN7(uPakxuB zp?kB1k^wrd_}-vmJ$)(THNhQ`K+9O_o8fz7 zV<4kh)f;Svh#I6b6Tr)>#9Z-kUhY@w`of4CO9-3dmBx(ls#O#sk_h}wQOkVbV6J3h zLPH6(WBV1~mqlrrs%3r9VZ}yY$lAFL@Yi2~O zHc1&*Egq-`&hG?HH4T!czkW_CDzR+3E}wdJA6nIBU+}YLEI{Mw-k&}b1B}V-OGnqp zNSMl!fbevf@*~f*tezg`UjlQm0Br7rD*aFXomkyCz8+7gM!d;=yQ&YFitNI8^ab8E{4bcx-(Xx$aQ9>=I==))B8bPn$<~$PaVpuB&&liGXHL_40-I^||Zx0YPLcH~wH zeX?!ClU-@KHA7+{CH5g_X)wPmEEM%;f`*}1q`&x@z_TJ@%kmpSDTeE|vLF4+v{TbL zzpM0lQaGxqGlzVrTc?r-JV0I%^;f2@byG!V1t)uIfkZlVJl>=<1ZXDO3sd9sVadmx zsGA)d03vR z!-+*RcJkfWO&sCRFAGJf!LRB*<$Gz0CoXX@#W)3xq)?nzT=p{>X=g`ID^2-IPX;6P zKAsxY7ZPMGg^C9ouAN8qjBx37#fDh{gk+C$f-iwBC>$w(e8sj2=c5##dIXcC(&V39~@yC zEAfQ$2X=99Vct*dupXh13gW6r{JI_+6b-USz5BT)V7j9|g_QI_^=%~;+}`TJ(3Kx zLi7?2xkx7y1G_&xao^^-sg@H!k1HS!nfL?=2##tE^;tn9rYpj&d>Y(K4cJB}#O#m{ zpW4Fxs9i|LbDEoeD@&*27j6DkIY)oaCSF?fD&voID|pd;r}{=)&|$SVzx@5P+QFNb zOT&U%1Xty@cbbBa^WS|*PA+mF)X|R(#*}ISAJ6)he6LpiNef^UqSV>XnesGe+B#_J zp@~BzBpd$o@hc@X?>|hvddeg%)wA|JOqsc}j1sFU`o*wBb$w2S*3h+@Mtuc8$pTKv zkCcOUvyrGq2sV0m!#xQoB!o;Kq(v{inWp33L3oeJU29|~Wzl$}hsY*jpB)+*I>EA} z8tZI5(}MQtTnO7h4_jg=UP-S1$bWpCbLfsUd~X>EXZvzpvGDR@_BQ25yT7AU%p*k` zyqHYY%PwIlFR~*!BrvOXRyCjma-{ed-9>eZ8e;x$8v-2Xm&mpx40 zxWcPqPQpq5h?_I(lpinkkG~w%wqDrKltTocDvH$HY|ReNZPo2-_LaX8_%H*rOGkBs!$UUn9*w-3sWgbXL7s7Qiahb=mkpKe z9jE+KVLlnH#rG$}xVLTFdcI2-=ZD;sVX!c4x%BA)C>J^bc%NKQ{3WBP82rzrSF5YL zySDxTBpq`d))bC+x{;@rgIkFssga5P9lD-`X&?B`mOlIbWbxcwpXbCmC`3x!`bkUJ zlBIQ^3$q=Xuimx5cG)#K7^$?@z5kD?vkHh~+qyOG8r&fS3-0a~L4&&m_u$gF1r5R7 zg1ftGf;0rzMuK~A8o9+ed!PG1@`gZ8G-t&esp~#aSa(?e z)LA$Hx+YdvS9b>JnKXjH)@L4Ycu5t6K#YKYT<+7SSHGvHD+x&|N&WZ#NZdl>Kh#r~FE4=LDIH0X2D)z=M(&IB#A_~2Tw zfUrmTz%X>{?$(_wV6&Q$6iw5{S*|mV?zVJzUqf9u85wxz@k6%5?7%>2y`w=V*m;69Y(MN9dOU!w^ zDw7s;-5g}$^&V!&v8_v0=EJ?bBNM{W-|M6jwGwTguQtE?HdYuoS;%37X3Yv-O}%cV z6>27p$P-nPZ03`0WXvK?3ELYH=c1CJDw>+Hjb!cxKYq;2 zuS)B9q4FIWM#T6Kn$7)+bMF6RIn{b45waxpK&q%h<%xF)YFsX@aDbNCQmyAE8OZa1Zq;~!sm|aH-wBmA!6}ka7FDZ9sUCYRz!S2m zboc`*K*Q-HKo_TOdQpdf*GG1KIF=#`fW+u6?y8b?!d#z%ApSgPQlivb6#u=W?Kqa7 z{L3^na$=&Ch9Fh9ui%B0CB}1yz1f;5v@;5S)^leowf){DF`24T=2t-YIenzm<9>pi@#Tmi zu~>_+ZnJ{qCsXqL{61Vt!m>eMM<+eIm6HQE;TpR^&Ck1p#*io12R=v4xr*hlL4Bq< zzF_OLeiz=BWf=uxPm*+oM$G%3C=L294ZhCeU5CEz^l#sgF0)JSzfeTaYfy<+JR_<& z*9n>Qwprf}LoK28XyRwPz1biS7Kz?X?^(kT6a0ku$w`%$GS(9)LFq0GU#`?dU%>s_ z0-&Q+b!|$=!CJ>Gv$4QehVt{D3xrcr@my;5dlp__61Cslp73PBIL8bEA!}Csfy+bN z18tV7GP@mGSA+6-L2jYe+qb_|)IWuZhVz?1;#qIK_S@fmbquV1WE&{)+s$(s1!B3x zg_xf?{8UfxmhYa2HjYHu0&ybGCbm}cWx3b{TzKfSIZ*J1uqNUBtT4-x|7r`xSw4$p zxo+7eYN@|w5T-)LGB;iPRq44~K$6;ST-g?QL7r+NuHEXEjI}wYdyZR`ev2S?nOPCc z*&9?mc6m@YYcIw&ih8#%F(FA^$_s}LkaZ2dFYz2!-K)0fJtDBzOb@Ov1oj(>sm6$z zdGx$)jT(H|bAtfn^%Y>M5)ly*@Sk&+9;o#~Q&WjWBgcX)YM?7oPV5K-o6i50e$Da= zZIt_r_a~dT&RdQKx@pr4DgC~s`QR9hgJ4geF0~Yl9*mB_3q=E0BCID#N%O0WI)r+x ztjtnMl0tJwslgB}zp&MCermxgI^g|s_yYG7pV@gkKcjc{n9u)BFEtP1|1JV^wY^Cr zs1?l$Kcyt2+7u{flcBLv}0+lq|#s%>g2-fE2n_wn9!;O^}^ z4o_qLKYw;;`Kw_N5$P!BcOwETI;6E*x3$P87K1f^X1S>@8;ctSE(y0uCJ`}jblI=h zpP<(T^y|fWuOO%IMF@xng~7fNU+?QK)eJI&zrUMSjv)H|RI?{ErjjY_!Pe$}90_bb z(Xc3d=>e*)kRkX4*%!AMxtQIZPk{K7co52s)Hj-c4ZsE@h-Ci@>AuH z&L1SMSh+K@4@UW)qf@$`@PHc%HTLsqrK+lWI}Z7$!-|JjbeoRL-LG8cd}GHt;H~0k zU^!L4qF`FDh)?ekbX)b`ctXRWZnav)DWY-9`^6aj%g^`qgk#pAiy7MabpZcG)#=kz zK8M7h;w1k1b>CFI9*`F{#F*)F&zPv8ZhZRWdK`E9HUGD--O?j6a5=)|<(a&TaV!99 z;Zbs^%BqUtP@)dJL00L|qRP26c>Ar1Y?ctaWS?fo%an7!v3=(-e?+V&B|kt^t8rDp zol)Js$;P?{`p~XnQRFEOBx)UllwrkbXkdZEDQJ>--KrLVtQiA+lxF?i=nnVnwG{Bp z{o6dSxT+jO%JyHS;U6fIy3#3$pJ)QNmPR`lqPs=w^Jy{i*_tx;hQttGb-r-u>d1&w zgF{l#Q>SpgV>Q;^VgW@M_I}_`yztGkk4giWT8c8yVidS|6kn^dbWQeh9rl)533MCY zN!cmjZ<-dU=GZX9 z5|(VT&Si>`04!L$mAx(j>j#(y z`)Q2OP`Y=@U=3Jc!9hN%P(#nsY&cNED*iX__^YLRauJ(`l4bGJXo1)mK zRpt`Tlm|Fuy8MTcSHinn#yd(zTBbsGNDK9o!G)C0pq??Gx1{gOu2fimcSxwJ;sS8= zTsZx^y|qr^?+FPR4YMgPPnpNKlhDrt$e2|`&KN0iCtG=A}1~w8A(W zzI-eb#cF?UV7t5@a1$>8T^Jh5(nel*g{EoOUTOLAL30+`97BgOpeS_fLvL$4Q(o;c zWCz8V^r5-F%Ho_+9p)6UU;YudS1&yRi2>lcum**PvH;(^;`5YbkVt+K4C z6iX0Ec0ngJc72w=yFcUfDZ-9@HwN^YwG>{7?2aLmf5*X1jX1VQDMScV=~IfL%kP5( zTvLu>=+kp~!bxG*TBnZ>)Lplag8p(pJMxxtOo-~^cmWYRee}k0|3(@1^X=J23-qMj z8NeQv!e~#QLSOFAEejxEL16z!g2>`_2Nv{Zt=2Swfd}r**2{$feB2UmkJhg3Gx3nz z1#uZL+Q{P-p08kzb(@Y1!fq@?LckWHK;Km5M~-ih#tP{&AeEz zx5Oe&r?M>{DYPu+kcCAiP~Wz2?6imxFI02q=fAFTgTmscXqS)P$?9k~KJpL9(C5mx zn<$E1WWV;QYJ-exIHz$G&W4r78CzkRek3@ct?}UfriJZLM}AeSV}Pz{pQXVIH-Ow? znNz0u_${pn`7xictVs#zUD5B@sJxIQfV_)fAl*cV2zoeO9M?qi?Z^js=V-JyJZ6Aw zDyKgY+i}>MhR^zqzJT&i{m;?Zi=~l^r_oLk3t`(ZiEp`2WSA^9_a~lpEzln@&3DoA z|EdL?j&moe)ln0qc>%stUS{X>?d(19H~JyA?82yK@>jBlnx)r$B{YG!Ia1Qn4H3$t zS?6Z=Tlp?=!)G+BjeCuXUwhZ=TwB1)H`RT=?CU4X`<;PHI#j}xt_xb1sdmkyWF~jP zP)|8uKx#$16%rWlFXEKOCN$bt!z(+s~fBrEQ0-XgV9u>lJBJbju`le!%9X38s`UNYI;_*+UWMoae-N= zZ#$_!ejjllTtQRo^vJJqMd(W{-xy~?R2wJjX)#yU^sbSntg%VAq@{%zP?4B-#?pd; z_}n~z&3>g>F7@(4KIBzYU;s~A@cN{&q0Z9%r~2%*G)@r0Kc^{*J0r4T`I7c-NcM4D zf9TdTc04YpE~(qEf{AXDR_OT&aFlKtQMuIG(x}F72w3+~`~JOtY}r3hn<}>Sc|$)y zt?;$MEsN=3?Cf-^l66AZrQy~2FtFYzW4F+-TtKZ*cY$s8bBHSb`y^?lTKij778dI7 zH7;bcsJDDkyH)uh)FSpLcCplRkK@_XH*|uAh_Y-0mHe3}{zampcQqCgGV;`QQTNL_ zkH@)BOIcWw`X|{`*6Ivfvn{ofk89M^8&L(adOwPegp% z=Ap|bk}xrg;{r4`vgWx9@z`YdFbL3ORU=hb-?l9-8ZbL55z`%r`x*;qxXW&wddz>L z>Np+8Qx?38F~hD>E95C|+itSCb_}kO=ivO@^8LKLN}De4=4Ue8<~s2RuR)u6%uZ0n z;&S8n2);u_2u~xiZ~J~Pv(1Fll`ofA&Cc-I#S*^S_ar~@RH{z)44MN&vFs!>@JY7owwf91Fu zZiU8W_30#RA2;IAQKfs~*GWQF_{SedBROohi#<>3nQI<?3ue3WOo$UB{`=or>dmcg?66}zMe zRqP7AU7fFvpiJA%g$9|`Q!Q|fN)bz%Ex(DRHv{VIc*iYm6K(Q9SfJD4n3E_$^tsof z{kouuk;QPj3_qFWhHR^}mG^p$JZ>M<$+ynzbZH5U&nuOyZxw+L3bE%&^;Q^ zX*)w=o%^LaDQR1~#v%RVx1Z<}=sok_q})Q{%Z!Y{ZKv4mRFl%-SQ~&JxF1NKovgQ1 zW?hd0#lDmQlV|OW;^I^gKWJr>cYOdqF1m`ASai@j!#{cn&X`I?&W|OM8nUddO;qgM z=2xdNh!PiQ+?;M}qqlZ*cuVxds0kv&u_xhL*{!I%S%PTiVqZu2+P6P=erzW|AN&*1 zR5le$r#K$fZ0Vx)2?NV+{MWU8hS}}|%vmZY#dqFmg^T#zsY4zF&{2x2t#+j$t6~$XERW zOUmpx?UumHCLG>YZQ{oLdVknj@+odRqfsM*gs{?}Yyg^go4hwumouN=*fmFXmL%Z_ z&LLtOf#bSal6?r)ON?lL|ER$V3Qte52e&y2*rj%EnxzO~%t~xLF)SRLBD9}Ao|bXG z22@xXW%S?jo&ei274RzO=jTs0+3O7q4Sl%&k4}*bFo~4)+PAk`9|_lq@E znsI|L{yldstTdeAkLED;CiAhYgs*gDWQR0ad!!OvG?jaixhdt8fNR>-M!G=$awvlx z5-a&AY}<}>8nS>07$c_eNQTr(kUr^tVJJx7$quQKfUikxy5f_T#KWa z#&+gZ)o%AALPJ}v542LQci0tqGw>tVb~#VX+yzRTbXRAm`d(};;~d9=#fOR@X*>2Y zoUH@8VjS^zfazi zaks1qD+tfbmZX)!)4%bqu*?-5*P4s_)(|9iGeJWW=20Bk3nq+=_(YB`E<>xLukdMdN_YG?od`WvOnYZTxx{YUqSkJC5sG3_s zH13kAh^o>F$BQcjp(qF|^D=ZOYA}w;=>e_ibNM5EH`%aJqVjw%HRtc|%ZC^b5*tj* zYpAx!FU`NN7?cE%J1|)qY*#UIx?IG)uk4IKnw5&E9`UP3gXZ=dCBo#Jor;e~ti_dz z>vk^hKFbIoT^&{&5>#k+QiRH$#J+6}C0R)6LNw6DRM`Z5oI#$5_Sy1ksFN&vZ{cTP zelb7H2s<~TUH|BDB-F5$Gn?EaW@jjX*3WSXV_22mh9V^^vT+_fhAV{s!S8;bp~BF< znd_s1!VIDv9lQ}xZ?)*OyR%kx{QckyXdc9TcEm4z{1C=r?O3KDUc1L>Q~Eg7rFf6w zvMdfM`M-}>Gj+nH%tot(kdlBhSUl?v?Uh-^ep(^0_wDubInm0W9n1WrLielGffvyG zxWpMm^}@G#F1V(Onq@CusjeOmsz~FJ!_|qu{uCjaA-tlB(U?g%8HgL!-{0>#8HlLL z@30s(HYUQ)DO$~eKHB^cv@n9;YR~;+h(v`C+rP4;q@ri@3bHYNdManAx-(^8l5}!A zohI;n#5sG4EV^fQU&_C@#8xsd$kz_(RHW$TI&m=`5B>gq^KuWX>vYjYOYifV)~3pw zQU#7fgmCP6 z0|<0u06-4peX#=_7^lq)!+u1h_^imH*YdXd2{8 zf1=gL=NgZ3^f^w%va)p4zZc6uJ{+-3?XNNJ zO4zQ46riL;lDrO@k3Y~9gXU`A3iR=D^f_slbmAQJJQ>uOFZ;GDE-XDpKN0s1cE*E;Eg zON6coMs&)XqctqO=F|DzU-~%#B*WwcU*1u4t9F7Vt*lZDjUAF`9DN<=8pyc!$44`2 zy%xJ>yVU119ta-G`)|c6;6snM>{s6_LDSlsPT%-*~;`4_ZU z<6lR`=lc~5u0yQ}3k!@L_hUIu^Q@M%OjG(W@j;!x*Io-RJ{~rTgWR%j{G?1$t9yUw z+y8u(3c1G*5pMX{?@a4$dbLEc&eX@;`yNZM9eSKZ2 zq=D~*K#5emgmlUf@qIp&`F*wE5&YW&641m)a-Ew%26~}a49djOAuU#8dJS0S<|ibp zK3I-2uIg~!4P>gkTzNva`AfzZ&Rv3x>-IV>-*V~uybG;;cIHdjP*gMKcZ4qHd}As) zg1f5v%I3(G#j(HOonodV);k^Z&F&TS~cs1yX6~q1{ao1qBQlsQ#zV2q{ts zva!FV=6j3V@1rm`M+jlNXa`fE|Upmja^|JWv)#c3&Zh0*u zJ-&`kA)QjImYiIS^&c~(qRO94F-|(S^jAEu-pGXL*(Mu3Tw`e3=NMddu*v%PHyyLK zuR`{Bj!B<&$GMd+%)1{OiN8p-GsJqH!MmqYo=Jv?4Q-fMgq}T@x)<3zhjg|WH5Ml< z#D-M&POHC%bvH?8Ug|O*-^UJL94ug;KxW&Wl%q0JVN0l#eZctmNybYv zjx(J45k?l3J)3l7wO@|i?HvM&Uj$EUBEtXJlrc))_wn z^H!?SqPQVe55M?~34s_~-s2w$N_{{s)SlucmiMh!fjODH_x7JZsg@VJaF8?K1>05> zso>W-v@egC8iAPy9Q`Nm@X26k%XkQ@QGxv1kJ4i>W5-m23x8tq9@T=dp~P0&ZmVlQNWK$X_6PnO6tzxB3v{9dQXJN zcLH84jv3g;3)e`nr!oaMHS<0wgX`*WI-X9dQvs0Mw(qe9q>@!Bhljj4i;KJ;*+W_# zGsG7uKKp){SG&_M1q&-xFtHK+`R*F*c^g@65IH-?`-HZeL>O0&w=U{+GyleF{WJpB zs7PLZfQD}EG~oSP1b>qd$8sBR>2;uuzvi*Ug1p+D%=`DKO%AJN%fRY-_)D|zvOCdo z`TL{u)7>sDO>Y-d?F=p{{Fpw#xaEFPSt29R9(@73_|ofxozMkKC(p7{p&d$y;x(yzEr*S`iyg6FyTo#GKZE(j4e?{{SXXC%xmT_T}4Q@lj z2#N}(>7Rrl+)=z&oKL*7B7J&QNl?H_%#(VG=N zwjDP8aPegOAf|Il=BBX$d2XuSBnENHnrL;4<>$*`;gONmQ?9JR0QPn(->W{psJ<_M zq;YyO#sSoVPo|No>Q^^1kHhOVOldhS$B6{o7BCMw_$W7~ekH6Ck!3C+V8Xrk)JAA)Ac;miENYF>KZgrH;_)lY zH!&W1%}$A3dX0Is`S@lbm`2R#M=Hg8VTvXI)3mSf03=Le0ddCt0kH5KR+H4g`wMRQ zyoHX57^(yWu>T=(67s#};Ns$%Y_!#~12jG47@hgRQO=CC$Mm4icz~o#%gv1k7P*K< zC=5Xgg~Sh?zBkkZs1D0-w2{`aIqEly}uRi~2LZ|v*s*Sg^3 znBtP@^Bbj!C_ zb!M8YfP?~N{l>V5|A3%nY@hvnPOKkD=#~ZJ`fwGN{qaIB)9q)$2)k3~b9o74|4b{p znbpmEE5JP-lQg8>s+hy8hvMBx_I2b;+uue?MmSx?WsgMR5SH-a5T>1jOR4c|*;NqL zO%c8@lf&=6z&@ZJjb=++0BGK>2Q#RwdQCFGXtJ?qV0TQP5O#)QmsbUjg14ZiMrB!u zGdSCwtf3=K++VCnDXXlQyI?JD-IxHVwTOW|Z0%hX%!w`#v_T^c@7nSjntpj`+)pBK z0mCgK@PnBwXtL*jvVl}}%CE`EnqL62GnCZvRjQlcEFHt<-za)&dZFK@5!fkm2 zC|7MwJ-V|kcB^vOSClO`*DlTw2t?AM%C>f)?(ZvKt_#k~LmuF0UMk=_D`8*efd_9FtkV`mC%7Vg-?~HD7O!GI|5@)oeJqg|TygK;Z#m1{!ll~Hh!ysf zAjRVE8@KVI5sm{yVo z7PH+X`$k6IiDsFKfi4R2^V2IV#p19-nfSykEchXo?(R(!PirmC1!D97{x?>PFvxNN zoGJ*$@FrBW*m(e;2aQ(#fRT!INmzC~9baw7E6-RQU>mLgXHhD^xj;}4K?ui}gY;Rpv)(mzKzClQo4ZS1rg z^FJO_tYO94f0xj|gA)Xj=J*7Y&CCt7FJV5fHSbcNR_&k`Ch0QzH(lU3yR4k+V{ z2p0ZIw^;71GL=1|(R{11LQ?MYp6ybxkFc>U;rrBhQqucaHoZi{&aTXlRt_AtWv_Ob zR@5rqD=E#*2{laQ$GitZnI}7aJOC<-oX??JYW}S<)n{)Zwe=kyL!VaGVw4j*O{hvj zv~_XMiGIpFOXN`Ike5zA*GeI7XK&A{vpeK;*_wF(!^y(m#cTI|e}CVbQq}^A zZLijE-oRsji+VxU8|@MUsg~VtsR5PSVr=p;Vpxcoxm<3u1NWNbn)zBV7L7#AS0ENx zj9JBAWDhmN_M=?9xfOIb?9O})$#FA8&z#S{5305df%Z=+T(x4mAwtM(i&*qqCT-j~ z2k7PhzsyN&azLfFBR!rEYUdk2Tkj;I10BDV^#m&PDTQN8 z@X0a9)2*MtVMF|0C8fL`BDsyk#SDVJ)AhM_t3`Myj=@(i+wMLcvlEHs5lRiyj&pVq z1>rVCT0o^!)Yy$&U=wJ^f}_bm4r0)h72WDbm(;ZA2x$)g>BA@AXKc$s+VQN7{AFhrR|1jo48LFxK*NGys)92=7mZVHyoRw9P{i9^8 zREG-?ru)T0>w>+x|0;Fx10$LX2<^yMH1@UeSzazcVonG|IAPvBe@WbK-~ih@Q#OO` zYXs|iI(v_wfaQT{xH-|Am0&YWO7>mnO(Tmbe*paSBB5eAO`e4H#xE@epNZ77*Z7}v z9&%*@%{?)%P2vf<2t-j5;|kHzc=YWa!QQ-cHa}nXM@v-=OPFZz;pq1WXwM-wlw8*H zni*;GR>xeb7a*cFXy>G-mqBT&;g9fqCvZ9S<8r1Gl!Q>F!!SzUP8g(ccn;cz;AOMV z5m=+~DPe4Wd6SGRkl2VHgoE(!am&#s498FP9XP`2mW+Pbo31!s&%E6@o{=iGvSO?{ zlaogm+!qw+FlOB;xds!74M)(3I*no$Z$ztwL5;b$C@6!=f$0sEQd;O0nMeCLcuX|l z#S#$3Ac8<9OFQgZaB0jtewUejt+v}$Qt1)hV3i&Hvlv6Vgq`2v^1hkZj(TteaEmp{ z%1~>c4a@1f_q%vr3@$ru-ohFpqAUqtovzl}B!;9NL$x+mb0~WZcDsX1BDAx-AP6j< zgVTSs5I&JxX0IgIEVulTDq;5IV@zcUTt&|z!uGb$`mv-_rfP12W)*2>*rP6Pp`un| zeu3z>##F{>)(s>V=nfPU@z|?p&hg+Qr->f>PPj34ISW;KGj^!LY`J}vl(h^99Gxi+ z=RveZo1FmJ{Sp||M{*)LGp-ClL?_%^N0n70Of2ltQ;Qx3r?HO1Of1xzIRl-p4Kw)( zJXFa5^=joQnN_a=XH3Cw&ev+>;y`3aWJsh7znn?^h2ua)i_U?<_7HN7uA>E z>0;QO*DK~_4`=O$rX4>*Z-#-m)kc8{Fvrc;-d2g8n{h}GdF@7nI^ccDx%6`qx{1#h zy_u)dZb;pH1oF^xWiQ)8+;v4fGUVD^uY{!-efAC;100!Fh5B8h1pI6xWcnlYh@z4CmJ*A21@ULs7( zvk$56%Vf8MIK%Ki+!1u#+^-S~mpL|$Lfp5kZ+#EQe^|EIbYpyfsC5=fc1#OY1x?IN zXRb;iJhai!brqtCg|;IWbyVi-B81%cF>Tg^a+gxdYH<({2`v6V@|T=z;wH;(E|rV@ zMYwOq7okdwFnV8m@cUAKlClVd&K6%PPqy>N+9gsDAk>M)R6#eR*e@M9(C+ashU2K>7_vR3h}x#yR8j=fyPgFT|_}}|4Ms& zj7!}`x|Ulqx?2wyr&?thM%YcvCI>r%gsCj0OMPVT9CcPZP<6Yl`RTK6JoH_!iAA2l zWRom~7Sh>XW@ z0piTK$~*EPI%_6i`q2IGHwv<7KU-@yPowWSt9ENP7iBfy)H-kObF&vfRxL&V?)qDZ z^@o^=WuiYW>N#pdl);vnh~f46Jm&cKC15p_02o$+3__>abv+T;{?gt`2NuL<)y$Kv zBgg)l%y0+(;=xjx9P}moi!h%MYJf4Xr#eV|U@;*BIYjs8S8Oy{~L2-f;GxZVI~W z>^*K-A^1DTvfKg*HXP=^@a>kH6p>9I2u8B_gzOsLn$0grWq9c{0{~95WmCM7#g;sv`o&8IVA{p?{5*7m9*pChh z`YACH5sc^C!);=op5W(Z#m670j-kf55n7eHg^rr#1uZT3r~Z8CQOWj0$c`&9Cc*6m z^saUgxC92Q{?X^O9lp4<6~Idr(z~i8=b36d*`ML6s%sb|&gWY_&;LDg@H-6E`iT0ix+0T?E~?wZ5b5+JNO8$yKno ztHXM=;G@vWBC|mhs+QD{JM@F^f84USv@6`{eHf=2IHaVOd{1ohdPPfQWwm7t-Qq*# ze6ZIN=qUx^q}>wfMMB5I9l7-*L!=8(?n6EqPTLz`i_7i{pCG<-4zNmM&-!T^7g2=% zGPk%{KvvsAiQDHfhJURGSjfv|)eefG`FZDN7d zXPx!_2p<}Dy|yASz3aF+T!FQS&HKaZ>Wi-7p2+&^FlQsH#~Jl10&>xwDN4dV(Rf!> z8pi)MbEY^)ItgqZ2u$ytiN%X@cF96<3I{`wh9?aODWSkV-oq=@mytC$n;-sZmpc)C z77xOc)XSzONf@@+BLPX;iH?27HH#!*hx>%53+))s-xN7oIIU8y8!2<-6I2S?-EkO< zB*=D{fa}W_=i4-Te#B}v^e25y9(r1_x4?#(V!%PEEFvyT)W-WsS2G&Xw%BH4On!OJ70Scx@{>Sd8EB2hI z-Z~2ecw&pp0v^V``gL9?u~ANt2$cN!3(0-e1?aqm%W9@T9=lWICM!n+X(?0I{gCv+ zGQ4^@vEqxiPe33kI`QT9Ugi2Z4_>U!zr%m++~0RUY>uPxO7o)ytM~yw*uK~JWJvDM zBf~D=RzmcL&OlL5Msy;B3w$x}LowF1dYo$UXwoV4-5g#t$1Z5Xa)-2zaD0--q(RF~ z{`!|JV7%5kp3c#fL)9dvWKg=1SA7ED)U=AlCI}8P#qVbrh*!GNhhk24om(d-ar9m8 zey0At(yv(F6XP;_N-ur!RK1II+^3J$Lp{H5J>KK7?A1^fo!r@SEe{%83qrkmPkl|p z@`jvK^}Sye9Xu&1YRBzo;dH#W*4_Pn*b24TYquS#ye<#hJdx|<_dNQ%MGJMoXPGHN zlxicWZVKpbEa1eMtQsP=qI(M4C890)pLe*MPn^GgnKGu;_}sXt!vte=yi-jY^{{In zt2K-_6EET7G!t7r&o0p)5^QRoug%tp!Qkwua`AsfacDi&$mG4k9ie10f!EMr(!|Og zp~I4z%ntxdCi@s=KP@4vDwrc(y-ZvX&H8p5ELwpL2u?tqK|r&xn!Yy&IDNV`l}tMr zu4pG~2sVx?9ZvvXzTs-L&V2Opyy36t4YDOGj73a665zmm#;rRY;8UTpoi*_TD!$Lm}u>%yhSvWRXk1d}q%PruFm`AjG$>Ypn zDa$l0ZC`h6) z{P8T_yNZlwa!L*~4z0W5o?F|?9Qz@XHFv7StU_FHL|MXEIUqsg#a2YNi@)ggwHH04 zuGZT)#J=y!4ZB@n(LU$%pBMsYmb!F2w)>noAi?cQHeM zOChA|!{~t!?YPlKhqRz+C6c1!FCP>)U-s48RE~d2S39Sjs9krA*JSpRK|TmJcsp<_ z@^{G5cHA)} zP|pbe>)2q)L`-}4SXEz<90@lZb zlGCr>zNuX9dx~_WUj&HiV$QopP1t}!@rNo3YQWI7d;P>cPn3+lEN6(tsIW( zv6*4VodD%JDWb;~A)#k;)n_!(Ds5!*Q7PfhYe^=Ks_hjU??3qM^3r}o1Thgl1DmAx zoOm!3VocIw^6XU+X0}p{NN$q-Ms^pse9ll+GtxQWZ2gZL?m%vR(x7y)hBoDMKr#e-8rU zTvMkcFVp#nO6O(8Vl9`1VK2;tn9l=DSi<4I=fhqU+uB{R!R6|eJO>F7)pv3tqDod5 zzqHQZ+e69xZ)EAb4o>s>C3khj^$7v6^U_U-xV_0)5;1^is7dOAYnlHjmx;vC`nc(IZwNPKdvi{@t+=FLD4sZqWwbKX|e$YR9AcA^ zH*VIe>T;RJkBpnz3!Xx4V9oDTv9F)DMsxuvm$`u5qy-2kZ;<_l7h9vClg9`q$k4I9bWHF+r7|9sny=Z60y^|S4Nja_o42W6Fzno1O^>Em?`LT zw&DWbAM3sUQ*4xMa#vG`K& zf}zD6iHMtqqp4?M__mEua)%HnM9sU-*}$>-*xElUF$roA9N6#gS!@JF$)e_A(KsOE zw#vxYP@*=$geic@$jPbhoC5aJFLlvx$L#pfe*5Z^)y}gxsQDHewesVxq0zr4e(csk z4p`iqsIb+ATmrd~&}Ov?i`+LND_{tUSdX2D?lniQNl4l$i;6H1L>LhHb1Zq+DjWb* z>gcfw`pfI3ib^T-a#cc&EUg(>UbT z7eXK9D)TbX2l@)af=*I;jpmQVngY9*TZzO5tC(=1(APYlKVfj!QTiNl8o=Q*a*uTy=0sWk8FU9$~`WudRap=XUvnE}ne~PmA zWRAlbvDaj1DM-KLqbg2HPU-;%yb^^=mut&&s+fk2l@asvxHAj?!XkA(%V_#(z@YB) zdx@Yce6O_e;}A(W!nSHA{MZyge0`Z$T;8c_yp(BZ8@9OF5N3pmatB^ zI5zpYE>Z9z-mYnXTYx90|IM>jGP(D^cX|h50e!k{vf2aLb?=+z;}ZF?QT(#8&P_*c z>&=>vt^T(;GGuJ?jlpMyi;u)8*x1vd%HzP&*gOGMevi7-+^>^2%%=g{P0;HjmHOz~ zFLYule|Jirf|!Nfk0ue%w9l&Z!b-tUAcDW>9gvFQA-T;T=fNzY0Y?wg3oW*)#m@BLD7@i8qK{^m1OfRDW{npm?0dlu zT}s^W9SsfmjiFK?Z*T8emuz&TY+G-oG0G$SJOJbsR1F5X^g)EXQ04B6Dv{1V)&KMMI+2*Rbw2j$M06pC^eCZ5!hIi!@m>q6Kb5A&( z7ulmU*@>$hN1(2)7&%Q4Hz>HUWBk1NJNo;^)!8IQhZ*%7zoH_-gG7fzR>c+r6KdsD zX`vA!b#w0th#4h@B$m9iEqA(E^c(F^`fGf{@gUxMH+Y(nPY;$z-CoN()?J&I8y-^C ze}j=9$vSuS!2-Vm#2x}s)NkQ~X#xMObDA9Z!M3VZ&gWpBz&8ho(#pyZjbrakoU7Ec z_4j9Bu_GUm8oGjoh|32O`=kH8`9OVuf`BfPvNOdrwCGf+_!>|c`18(IxAi|mp7 z24F@W4xS7vJi7}GaB4b&s`%_Jvd3hlTzrr(P-Q6bq3@mCW2qI(QtDL$Hq13x?F+Iu}@VZi&o}pKoF=q!{^q1(YvC=x;tA`QP=mAj_-A zI{QP5z2B`#+a2~$t=G)Y-wgDTW1kT9W7cC*F*leuR^O}zjxY16j9(ncT&J(>&Ij}1 z5a32p9)|&Yf|Z@=VKy}6qbi_rcdro2A@8CGIL%I7B*ne7PFUmxl<6plv=mdpS{VGIhP2Bn)&T1;)6dC#>pYbDh#p)pxyF9$Nc zWFcr%tudF05eL$nbT~t~{F>=Pz@PuGm(hyRiu~8Fa)<8paHgp)`$P3xrNY(7!ff9e zFWP2+7xA#o?(a;pW~k+RzkNzL_^}cd6SH?RaMg7~?Z(Rlr7_go;8|ry$!@8Bz~0+h z$LqM$ml-WEXjbCf-3`Z<-CbZq@f=7@aXPGQ-UODZhk>Cq4ok&yOZk#{egQ3qX@pzu zTj5h2cS>zr|4)Sr!r7$CwVZHfyc9*&LuJ)r+htAG^$W4BXcgzJ#b|Y!)dpHK>y5UP z#X79QxIvRG8zs19?f39KuL~^L9eb02L8Oj%DOu%b8#F}K`gh6@pZe~W>dA=#l&Ifx zZ?-aI?PE^kUbnSsTO0KEHB3lVD*+q8#Zg;x1QS7ZKo#ziHUWMQWGa_o5<7v=AWEr? zkOh$wpj=|HnPw{kZgEBWt?b>OqbT29f!PBB>c2bRDw8>zG8Zyy*a||MA}a9rTGh z_QIsRO=!esU;gVMI&52CjgJo{#CPdQ`1A1`Qxe7ER#vC5=Tk$q>f?8_h(CWm^KWDq z90Po+@FgjeRTh~GXj2iy92n0ydnw^I(f5gRug3JkM}q(JHP?5=ycUQ;9Yh zv_=}5I{?g}f)>HqSJl>grzYPi|>@Y?SQu}cT`uL{=4ja#E(ujfB3h4JGh>TAVKbH~cD(PA?i_=Ulrhen0 zu%rdQ8*FrV@pqdbDIx;HBg0T7GZ+wvJq?;0G7Z~LvO7ze&Lg5xwJ$g5+6HDb=F!45G;NEbyT9Vh3MB2JONkK(ZgBR-kQ zkP!F$V<;>lEq?Xk^54)vI5U{wZcI>Zc_|ads~0}<3rA%1FdGPRX#v7fuQ*Gv&~Ap} zQCBR?Mq4Zm0+X1v+7!%i4~-wPG}Jr|$F8U`IHc$(Z=_Tvd45U$mnXOIPSrlh#=%1Z z@PSKZ%rTYVHkdLkm7G*1RS|0T+iOb%`T^T$p4&-UXF#aMLB{6fnqRi~e#5gaKZ zqHGDH2T>pM%)Q{<8uv-u=Tj-wQlC5s8UY3)x>c^!v5{<*=tVXyoo82HdMRam$;nth z;F@CkI}2T}wbaCS^cJ-9U#v3+EbhsKC)R5C3X4~of41+FvqtQoPaq-F311J#r~XAB z*JD_L@1o4im4`Dzpi}!;^UQ^@(c6eMAY=TBB^cQ-TZ;&u!{(IjP}5rnb(X~}biBie z=3VqvySwx%)*)_4TezyWTW_QPpS`b2dGR{iLAH7Ue!S>J4Z9>CSd4-fs^9u(3eO`Z_SVa{u{v*D3;- zSE(Rt`vyJ^2=oQQQk8e9kum0Sm-Jq!5j9ETH!#hRnTXrl89uHVze16>_6~^joBsL< zC5H5$iHH@7=ltxf%}_vBmJL5bx+Y6#dBEPk{42-=R=MWh$VqJkByq3AO61 zbpg}-u>6y+V;Ene>DVSJ8B84I>#-QnAC!y0dKep(V~5Nm5|QiA1gc z&<3QJ%fqLgm>_l|2b-DCB-#xRE9*?lqBNT8rWlFTY_qL)yeFbDdZUA|TLjduvyy&6@_!C4d_~i%qbX9~au$%1hXUpzij1?yeLIMl% zbrg&)v0yF*!(4M(&@GT29QGoyv+6cTP;b~?xW&{^bKDe^_Lv=Q+`RF3It~Ho4U)hL z^nYA@JP16-ZslTRl$2q3L)X=v9!#O@K?D*q$Uf-j&tXaY&MXoDpbxwWr)`z&SSUQ1u7<*?ShXngIkH~nYq6MzZVqiZ_Vl(uW*xg<4Ho+85IZGYT5DrU zT6LVkbyLK~Vb%}9#|y3{=2_XWt$)N#BjgE2!j!T%xvs|je@vZaK$P9y^_A|HZd5=@ zB!*5gNkO_nI;CSkN|01hIwhsM8wsTwh6Z8ip=*eD&wb8)p7%R^m}}pdAGTUkO*nh(n6HeU?~3wUq{dzj*1)CoCW zRXT(X9gA{Tn3JmQ`_WDjap89!-zso1`?W^!ctS-lBF3D!%xa=j=z74^!dNF#pTBWUw`d!nDuM} z4QOyaez@=YHV&<8YrW(chh&E6d!}`Mm4XHxg>f#qBc9I2ajM6{$c$3EanBol{Xn+O z87Uq;ZH*#_{i5q|9nUz^y1XozRzz4C2St1x(U;us_~=|G3W|#NJ38dl-oWY*$z)`{ zd^prpbWz{_dP0_4>Z(X=J^DM#81ovmSI$#%9b5*Qu;(y6xV9PMm9(4E_#A{<=DHSYdo%Kfg(s86ZW|M0Tm+ zRFOQP+9EXn%n8(dV6ykafnqv!Ux-~fB@FOp#t>6kInn&RooDUV6rG?yR<}p?xcq`s z>_QyowC~+NfS)}a>M5>W*s`e9(3>`*7I}<~kpyvE$PU*Qkdfw|7QGDPJYWV%ohl8o<92s@m_9GvR$;-1}Fd$a{C7)8Y`fNJd1qax#V&P~}gV{zuGrCmV!{$*E{yqXwr zl{EjYVr;WBnsnZrsbt5nm6-X3@y9eQj{RARJEsuKg9lwoJEv30DckSGDN<9BBP~!L zDulbyvX9AKugTmCFhnV{7@$qn8SJ*NASt@ICbu|G#vgg#3V@rt9wZ%jdp)4{-O~*I zuCtbx>Q0;HvsX_W<+Ys{ubywxktW< z&p+%7B{&pHfon+{Q$( zD=n^b^BxC1o) z|DdN`GbT~9STBbofSIh`D{9uG9*A0{`1(HdeZFgOFe`C}R;@-_?jTonV9`a=Yudt!2rATkH#}!`n9|lu!x~p2$TReq2Dq4Z#cH?y@ zMg-vOYjJ-$+hvat@{Zym?ly;fLCn$0Cv>uzB!5+um2twWjAu&7|t9l zil{R<;y}k@OE@0Y2=>8xsLkGnPOr(jU?MmCuLb6Wa6n7FpS-hEp5MZpZ~Or$OdS(E zWA(?9S3Y)3b<{n0wZzB$=%9>np|^3tlcwt}tm2zi12*52C-3L4HMc$kBkc(H1IADy zh@E`^tc_VCrowBU(g{|j%#;{Lias!!n*V_GNMcJ^q&XIfclsI2y6 zyJG5mnbN%8uKrTu+qa7~XO;XXLJX~UmbF7(HQ#8f_GWX?g>kRv;)OUxj|!L#Dwc3k zL`F?V{6?OpBJ|T*&Vk0a6AbF~2if4|y+5Tv&obN%-5-Z=D5`%mtg)j3uo(#O4jV?C zrYM&$JYoq@^(eFk?0tH9U+ab=m zC#$n`+<~tmr192|VMcXMnS-i%#)B?4!SLD!JFmiBI)PtN0Sr>P&(A@$R8i$`YlwV6 zLxVB;R9H@HSN`QmK6QHo&G9qgPd=Uh4B12lW4)c%grXTZ6kBNmv z-DR+76R1;5Pgl}CP)vNH5Tlq8HpJSj^m{Qao$l0#xF|@nj1xyTz?bWv%3n2oUrRc~ zr*@G!2-~%IOtG~$-^neOV$3Q8sp{7G>-r3HL0^aAbut-8V-3xllew)L$P@op&FJraZ&pMTk>%AiOlOo z@7H%1sgU$RZqcn`O#_;xL65hBU)>ztDyde*BRMk5E474(AR|8)C}^*L?@LV@t9EYb z%8Dn-7@xk+`)s?`I$+&jl!r+e;y3xwIEs-Mv8&sy=x8yFd^9JH|1GJueW~l};>b<& z7UiV@wDrqx3d$q(fZHbKl0qp|#c-&AlUp~S=$QqEC)O=Sj&i~=34>u9JG&$RV%eKB9O zbV<7R(5LB2K87g51y3MP4Q3QwBKE>m;HWIS$HB{^8W%6ET@h5FW+44I{J^%oa*T4NMTAQHY+E8 z2ODapSay}knZGyY(POs@c5J_{e=rc@&%S3$*i;#NT$OBZ1${)z+p=dU$a`{&p>9{-glYvYl%= z;px9+OYC031HA!`M0mkMm+DC z{~2`VS)sZ|6FQx6AM$QNArgXno>qZ?a_ajOnJ>o!Z-(W1=qT2$kL0$gD81grNh04WRm^x54SYhUfLjlA+WVbMXu;4z zYuI;M?Wzj+BTj;A^167bO%6$DcbItB_%(uS|`FtF~S8F9l2dj}ej1jw7TvTb2v;cS&+zRMB zoX%bIv>dg}!wlpxMorGMM6EHm23WI)?VdgAFqgLpUfIQ^2Cc`pfolQ zahIHn3S@`2Z8r00%O6Z|50BM+Tx_ha);6iBBMn~%@(HX3?`@t`(LLO~n6dXEQd<;# z*hKXC_+@X}gdK)GZwOMm>($Nj#b@aHi6jX9jjJvq%tHFB-6#&jd&l6>zafUG@sP?Wwp?|UOixw7)Z zc_xJXs^&L~EoA4J_eUS4Dj+Ghn`tBnYE0dTdug;uf|%!aRn(x3JFrMr*Xb^m%O)O}CfuV@4_(r-{T#IBPz4iE;crgoWw zW(IvZl@9|;R|+JBiW{46dr&`P#g%*fzhdn79c`SmZ?oaAw{AQR!%QSesOUnPuDai; zFi=v4J7*y;s_ZbYom`3?%@bcT(Yi8@Xhx|0DuTWC^SM^&0{gv(*fw7~ksug^k`m1Vsn{)96pgPY%@*G`N&h4q6S z`D!3(zs?F2{ewbcye_u>eoewdR_m1hsL(g?IlMOb4mmUZ&L-%top?Yz@i3pV!?r2Z zG%66?qEcX6ij6G`(3T6KxCL6zZEOk_q9KdkgL&HiorI7jptXArrcBi`c9bEBnF}Qb z;-!g~Eyn%BaN9Z5mW@2U%X-GBJBF#W%lmTLWpPW60=}J-Q%~iU=W#t_nH~lB83S3n zxX<~^+8&`Z_t)gTi>XwWHIP#~2Oam@p^JK0y$d@QF(W~yiAk$LrA1VYUWKvr&dn)V z0#zX1zr!XcIXOFB)lysCoCjtA2XpSc{zUNM#*nn1qEUJr&!b1}g9f48a5qN?{Qy}r z{vVba)$9izRVlSTLncr*BXpI0U4C~BqdBLO`%UMFpE&N`XLhCNgeI9n&gk?;5ia!*1)PSr%J*yDs=y3!@xl;u$tzN&hiwZaDHt`3FX8S=xnZ0ut^jeiu5## zlQ4-BsodfN5=xY(3sqN5@-1YrH_dp5&TLklynONELn(C-&hfcr#s|4;5I-4u8F&}n z;xah`tlO*b&r&u{O;o#)s&EkK6#l> z*3MK1N9#{%CM%qDcwW}=g%rgYgjJQ)`#Wd~E6{OeCA|Uw<8l6)u4F}b`Tk_V5Cr{R@r+chf*4U4+&U_vKKrvCi z`_pQoEAIYe2r;@l29fpeH+azu7@w{G$-QV*ywD#Vy_bPN7 z*w!X^Gko0)pxb^Gy|=1ucBs6Rr@8- zw^!!s)U4eAVO-p~o>^6b;eeQ&XlLEv1;eput4JoMw|Yc0F-IX~!Q zD;X*Y&)crB5_qJ)5w&;&-wk5$2#Qzc$;LY=W*a+m%A+n;hj(iD%Nt(xA?&Q$=e6uI zr&$fs`G)7wZ`qe#{8z!7-hPGGD4GSKCj&hbX?S&^W^te~;jT)5hbSgY1_uTVvSWr| zL8G8_ePW*1t1_|}=~eXsa-Osv>BB|ZB$d&n1pY-oS1mZ_4&q9(qd9kIZ&w^J!7AnieD;JaO zWZ&;u9!ws3YHnVq(r3B$*R0FNmMd{QSU4=kdfolG=>zPi3cr4?%{D0UmFEA7oZ+g9 z@slUXiS8uSQv4+lW3YY1|C3l*(hEoG1_1@Q0tI^xzS6cN!p0(WKDAFTUY4Edq&g!K z9KJ&x3-J#aZ#K`mp#+pg&k}Z27IULPmdyq8-*rPPTJRu0+UOQ%-;uP336`Ji%h=f! zC2NV6PCbvNm$lC<>+g4FqfoYGO?oe0tk;OOnA#NzC2Ugvn@9MW9B;_t_WCkVmXNYT zsN>A}eBY#RjWb06XB5~94SLT&5P6%?%^?*kg<*CjLBXwM3iJxAU?SEIhO|Gs45F3u ze@+kXc$=7W?yl0FR(doeO5JxuD z^FN?v@O&Bi%9CVCYowrK)_q64Mtoi0A5vZ`y?iG`e_! zTok{e6rSU@8ljs6ncm~hoYsrYxD$kL@tVo6^&FTM676?`S87JgTBJ-=&494DA^L;M z_#Ncd)X>fY;9=?l@oCPm;ojf>|tn^-2fX&g8eO6s;>fNlWe*a)M>9C zzO{30*zD~EB@`fVq8?%o@wwcd!fH_wPSX zZzRY_e7iRKA?#F{h^c(=&ub-{pt^+YN9~N!f#t%<+h$Y;j1SuvBF^_%H+;A>w?jQ0 z7t)QhepG-sQlVF6IsEqK0UUjiocS#Lq$lFtHxknDumy2v<@45OJ)*U%Bb|HLk)?&=A-& z@Omj+9#R8PwG`!lNKuTLOeqtK^kjDBN(zg>snQNAO4@LUVFQC?W37DI7ZRo*OQvQ@ zsCUhoS1Q}4sCLWyiB^=XIUSZ;e-3;oRlQtwasdn6Wa=3?*RQ}C zBn}d%c)p66)Oadks$Ap9YPKFpAmM+D=zJCKv49%8#Zvt7Nysit7@&?D(0~3uz@em8^}J-70-oSK zzv5cxl&syXiGAg0i-KeJFC=`EiH0TuI6dQz-1nr4p03Mbpo8zJ3n48L#eVDe;47Ie zoZpC{X<6Fk@J0Xi0gVAW3oC1x6jEpA;>A!Iqw->|4wd9+Tdc98um1N>#KeqeWz?r= zrL-+)A+(%1YhArO`#x1zd>Y3kBr!gjKigU)nA{ub3AN=p*b33hpP@6xFCRn=Uj@%-&nBvo~Q$_BK9e!j( zWAxpZ-GvOf4IsY2-9d@y39>JpfxBtaTksbcdT>L}X+EIT3-gyyvq0!y0AtzLNbw4? zQITyK3t@it@5G0^V8p@tIR#g(onyjIi(048^86G+Zac1;Y0FU0)9h-puy*y5i@k$# z1vw-LTWvb~t!NIf^ZENM`1x|xms)0Cu`a#=p(ot5P;s5v zOcaXiOmi#Ee9=qrHawA0A~WVChrYUuuw3$Y8BCFW9T@k+#&>;`fbi}rgugo%SIPf0 zQuZZ4lyVPBS24BPd(FQ`&g64gXX#|IH&tASwb5d&d*cdEfq%r^9 zBa-JfYTrj{{s6{6!mey`tkr>d$DZ&0-gjvdtGSpp)j?{;ehfBm=NeVy+04|!?@0#i zvi+E-xTB4?(iwfYIOQ{ra#1&bo7j)P`BIUQg~xu>4@FS5M9-m3t$5Ptc%d3q0>}kAA(;E)}FGFLpgCog$7}I2YOSCtl4} zOgkNXXK+a}SN>zPNNkwJ+*9h4P=f6TF_|Z z6#_MJVwuiN*gh8Z2rr;;ku*QNBrLX$H04ovPKj^vu&(t4tB&DFjN5g)&}nE&7|Xt> zMvJaaa*vot*Gjq)5Hdy3=V|Ix%Fx}bbK^KystfE+X5!;Q2zwHMkMQIiS=pn+QPpV$v*!(L) zmD2f1`~4-A3i-lw%6pjW-L(&cIY+Ll)IXYBQr)&0_(Sng_G;*8wTrENjLZ5@w()_V z{^+cnul&WKq&42u<-@H<7}WzDjU+Z?TTwBotbRGN)AniOjO;`$cpy%9Gy3G zf+`Mr4-%4x)N?Y=iw5|cM}v$Jo8{j<5h-fcWC*3o-BQaW2VV!?H@4A2(-KAS8iqRc z&38H~?H{u4hQ0ds?J`xOmEe?HQr60*Up-1e`1ms`-X{u2y3r|#=?v=E+qA3vnPFET zSs6TeqH4;T#0&ccENDHHhr>2_MW9P7%XmknTO!0Xe7TB-<+z{tDXAfrXoAx1gqG2! zX(2dpC*>e9Y`0HnKKSi{xkPzi`O<2dq|eq$g?#6{ZRk69 z-MgGa<@0Ex#y)xVOM&#?C=u; z?P0TYS;4gU1`gVRsfOK}S=2UZXRcm-76+uaYhxGC3J|oJTj=UKAIeLpSG$n}Ge7_L zK#tuln^mk!{NjJKYWg6JxEARNA?XZt?a^YA4D(^~rAt>y)`Mr=;TR>Rn`3ZnaizOF zE|^ieZMmjt&@Ot5rR`~T|I$Nrc>_cKW6j%|=7_oic;WT78!aHZwJSBv)FVkWi)ScZ zJDR_opHm-iPpH*ymx$vYpam12%V69EYl! zyxtnUlU3>Pb?ft{z4zJZTTsfC>-k-2^GX&RCGyK>YSu-EXjx87WUPA)${gI{A$IIn z4(8p03JWm203R&jPNOntxZuC z{^T*MpPgSg7BbfQ!7!y19dGaqH4s<ArmsT z(t~HwbOy8#k2?KOeVp|88N9SS;zZeVj^@tclKqgfh*otv$*>V5P!-Z!TlSC6^#m88 z%RM&ja)`%cFGm~rH``O+c?4JFBs=qb@wveMV5mTubzh6_JsCFOOkw4r0h<;qh!KPa zWJ}vuB zfGhG8?xQNm`O$>dr=?3psHpTpe&`f^VxUne;$SCmCnWAi^LJx}r=4=6$M1&F>R9FK zAzO|OY!M<=wm*HZ%is4Ye*1=eH=Wvrl~$?C5yWPq7G0|V-T21>G!EY;6B z`LB>9mJh{SJCVnmK{7HC_gr#CYmH(TaVe&CetnzS9Yj#ViW1P#(=wB5RP}l8D}aME(Jt@@tA{>zAOu*f zj#Nz3{83~72Hf$T1 z(eUMl|Mw>RCYnfKT$qz!)A$5iHfeVmQ%HE}x5xlrZs2;jl9$-Ge=%O4P-`Vw;c}?< z=FOIRx7hVaESVW_@A#zntUHTQ4>!NIowl*X%{KHo_&Sgvun0>NFvQ&>$1=>^bmuCm54VfeNf zn_X4JcOw%}){Ufb_8#LWQ9gQxPa6&k_#n(pQO@~6eA#y5S4kKeG*3BIA8(WPdap1@ z3PHdsBGAqGIJx+}NQ~c66`rYurTftmOPwjh+GO_AkB{};7+bsJ?2&WpLMjeX_$p2J__rP!Z3{=ss~jwJQ-=>! z8Yt(qv-S-9WppZZR!wzq%;q$ohf~nYdY>}-YpsT{)Q?alpPG0b6P#S1?0U}oe!?|M*8?; z*p|rS=QSc)^q4$gTV<`6VqY^_jLSk0Zm=rr2L53g@eE#rhK-|+5fX_O32D}8Y$BNW z^)8fmJsyQA|z2aO`?uhf{>+e zxSd!aZX*LLq6zN?g$$iQXz2`Y&pT5$RBxigO^W|iz{#`tn!6edcOC6YVz>%tWJn(T z!H!G`bOpWzx5dFuKFFn6m_*hb9ToGA#)i)?7qBRY1>4w z2T+jKjN13-DNLJe+DhY-1yj+I{yRTjd_4P(O0fg#<%OB%wfUNWZoF8HLfrm^`;J%` zHY1ej0&_29utSc`>Cb-h=dZ&JHc0}@4R}WCyM(UR0@TIoKE`8d3cO>9Zqg@>m8$}?^aCFc+VAdPe=oj4a#1=^&ns2so1?cWZI->#6OT< zBq%9tHl4*$urPKtiRt!Jnf&Epf#TFOlBCsPT33-V?N-*)0__|Uo^EIbQ{ zqZzL1$?RzeJ6$lbfD{{SWGZETPTc4IOP9Yo31-9Bw7>}M&UB+aN4*KFF0AQu2K7)a z^d!Ji^St*9TR9Zzew`wB0VHd_y78qb`Ix<}yg0pZ_(=fSRAP=lK)7vBQj@f|_<>rM z@CLbf>kTqT#Dr9SYE}||V-_TNe}dAjVq~_M;Ki@a&yIdiF8A;k!$9~7z7sxWDl7T< z{p&EE*=3s6$z1+ygV5|q&;DV2S?_MIlqH)4_vo&W4*gk6YjYHEsLSuC0_5lFDxY6% zzb7$1Zs$fz>~||ibcC#Rj66eVpIGJIPjXRA7nP(h1K&jbT|ZvO?h1YtI}uHD zBnWqjKjA*@8#`@UcFz9Lb=u#P3!*$$QI;jl>w`3(;PgO>iIO+F2Gi(p zVOWdml`n8kLJz5_c35|4EK@SCfB&}5OU=bRl#wlOa@)=d@X&1s3$Lt)`&Xl1L*U<$ zN~DWg=Sc(`=Vl|FP)X4ES9@Nfsy{ye3w)IO+ukFPpUu!ptn6bOCJ_MoHYiqtt9w5PkiFiEiJ z7M&Malo+U!Ty3F-GYrB)pwETdRci9x?*tB?8<(X#5`d=O7VA>5KS4)*-fpuP$y|Ih zyp~S6;wp+C)Jke%pN9w6OB(m&z{u8Z5~&24&u$*EMLUZT=0VBd!TQo^!3%ytpR)X( zfEA@$I-(UZ#*)V0dXs$%LWDuLYh=Ym$H*p|Pb?y~1~}DIciH$9!gU7D#i#8N7@2A; zCMy4tNhixq_-X8FB;bu}a=hK`RIyzBMjo1>aC9H1q|6gRcbgpjj;omblm}l~=p@~@g-4Y$9ui4$j=2uliy(fA>(r97qCByl~UkxD>Hzb}W5jhxH+NF;=mvwdgx%Rex$e%7gk#9xq}WwDU*!truUH z?L~m8HxDfDp~Uykc?IA6J56ZGJQpH%-^Q&KtjOUKHUqZu1lJW~oadaS`EBuI>#HM{ zQsw;|KfVwA{o*fI>)yHhqn__aQ#$4gc{w@$>>l&uO%cpK;oA-2*0OwRzGh*}8^l zv;HIp4nBTY!s=x{o!@WLa??+E%Jc8fY(=b0V#&$x#rW`fVHPL3Ri)F05)vs2i|~ql zvZm4IHWT2pm34!?t~TgeUwz-=P)d|hdRF!n7IqQ6Eu)_-M#}?|w9RBL? z?bLCh%ad6@eh^&oNqzU#L~j1+2ba1)pROwS^`n z6&SSIw0U4?Q&ujdp?$HchmSCgJ)Ehfnk0BBnC3)M!^f~1@|LdG`nW_IZ2nM4t0h#B z&;D}f194rF;Abk{-eP;Lw|-3r-E@GZUa1=_Eg>D$OkI10bB|W?e->C(oLM`etfC_N z)|(bG(RxggxZizz9jimoj~-Gf0Y6x`)mlE4TW`!-H}NGOaV$(dwNr|A3|U1Qt*GI^ zz`SSAYs3DY=QR4=UM=`xxusN>rO{A%N_yNJB~^6mJ(Em#AC_41=*F%nrXLMPekVfX zC$xP_;m32$(>_*N(uI%f&dY6jPP<;G-R60q&`9aWD!< z4$=N5^B)aF;y8JDI$Lj%l7>D=9}SH0tNEfJKZpM8v%dz8$3>-=W?zII zgRqwuWpf5jO3NMF_UlGF1zo!R08B&DM8KZB%&%CcTpEgx_p0JrXN`R#7t<4hktw`y zCeMVdeXCah%PMe#yHeuqP87!1ba{bk#t5j(NO!=eKHm4(hgI9UMMa}%j@KoJ+FX93 zJ3>+*t}O}Ye_!L{pc6vRvW(t8gPq9q!Kd!ZQqc;OeDlHZ+Y_Nzued|+vI*WN&{Fgz zhCmFI zObleXS&u15t3x#cPCz!hy^?vNprC*m$7>LdvgNe4mx`cCbb=iqN8 z-@#&Crz74o&CamO#j;WSV;RID#4ap;Sl}+f?H6A(Uxwe+l>?xkrDS|H48B1o4AEw@H zm_^X=D%eOC;|!VBeHTI4i>HnIrXTsF&fK){>2gJz?{+sz-!MIKfhzx+&4smUh=XJ! z5i5TInd;=X$VMCXd`&l&sHmte(5ZZ|O!LA5=l64SbMxkRGwL$4WhUrp&{G|hGWHzQ zN9Dd3?@{791~FHe7h!*K@d8!FfibpNa+h<#2N!QN{=l&SiqH9sOOXHHyPaj^Wm$on zdU2lDLxt_{g|%5`NI`;)*`J%l7g~_}(*4?j((@O5+(y+CSymu9Vq4jt$Y7RGJup{c ztLlr5g^x~G?Yjw4>$LH^q$Xdc%WPZ7-p_^d3DCLhHl%t}$fl<;e4gaS&CFEN8#aLk zLKcyvL(PZxPWM!5^*>UIvJ;6DYo)y>UNMWE8(k{2vy#w(C&U-;{hIMj`YQ+hJ21Jf zZZB|s^3>1d;R5o&uW0%Sy5IgM8+8q?Am(xDgMw7N#(PAV$WH}19V7FxAVh7AbEPE&AEY@SX-8;o856N)ZmW7@9%`W6{ z@ObcL_i_IOp@e43UkR;dSZNHzYHTX9I1cf{_xt;dmU8@6I@>#S7~|<+X7qcl#}BG( zCNm%1S+)42t`yhEr*p_S)HraM3E#A^DcqXMO731ETwK`}9m=fghd*s%E5py#W5zkb ze(T^jLil#qeOll}s7US%HHXrR7j5}!Syje<@Kg`e{iSvoWu6rJEC7Zl2;0*ddM;yL zPp4q&>FY-}HAxWA2`ge#KW(DIXlL>y%-p3cby3e%l+{V>IlnNO#&@k`wim_7#AW?& z948?m;#|P^Y;V`0`VMqYyykW1u#9H5%>d*_d#4A!yCENxeMDbNn|k&1~BF) ztn^B_7O>XK?pn{CO_gIa6<50%^r3lS%-zw3X-r76+i4vkC3$KrH&u}Z?b4nj!WPyL zGfONyO|^(TxGmdW()HH_2a#g5iT_35XM8r9%YM05V8YUq4A{ET-D%!j6h=ZuakQiuq6YHNZQNyIg_04L{+mK&o-XkGriv!A#6||0sxqhws!d&R!jf^=|2EHI3WjGQEy zq^GCH0Dml+mVw*%({gFw^Rk&5R&00D;zvIe@A8U^)48nokGNa2J&Pnc0Kpy(;I$=|z`|nKPdbv=akF~GjH5*T-@z6Rr8fWj3L9%p0b+*V&*BG*0hcH=cR5B` zjjfhs%#s__TdmQ}$kAqAsf=yhy4|KJQl?})qo2naW#a5w>^l)8B_YR`XA2tOsI2qa1ZVVivdS=UfwO)Afx?-DZiu z*+2us<@y+Tx!OV9W>KrjXjsGqGU~7%OIC>}!X@>UHdS`9pycVZoKS0FzM;aLQRFFF z7kEvL2Mbh|*|*;&W0CHKw6*Ukm8X5tvX~mHyi!^DjDwqd zoKo7CSgFM@iW$f6OKfZqqV<-scHSKoq_eZ@LE-;MQEQiSdV4s`iciq%zZU|FcE$tD zf%%?J!*4^Fc-fWkqEVVN^h=LtPd%w=1%P|WbFfJ!^Gz=fJF*F8Y?DxC!Hnc*QfugJ1WSajq>%c<0Ftu41#5q-v4 zDpdoT#a(I>Hv8LEnvH~9MGeWtqm9Ex*1AI$R$vj|DPd(&Sq(iPI*$&PT0U{ zP~W?Pq)kyyzEUUiYMAQsT#boW!i^?vob!dPC&7^!{k_eo`TSAV*cKZ`W67~PrHCHQ z2)Zt)ikzS34a?QV+D-2taU5x5%VrYyLVABGtiYwy1C8g2L*b12L|72C=B_Jjqe zhvbll^PjJzOqTDC#lG_fl&cUE_yP7I4;B`k)}ChP-scF&a=yyWT)r8Q*Kb*y*n)GF_T)tJo;apGSvWs* z#D9OLzvr`7Lcmr=n1JsK4;1kawJ&@mLavYg6a}hC`w|p?BS6U4B76^&s}m(-&DVFX zR$;ZnjjNv@@ejs28I{x+X{$yazG>WNq@?-iWY1#mLOwmiu@xWpEt4Y;C&ViR=k48? z{5tAtLlHSS`EfB}D(99_?DhqP=}?d5g^KjIx>DoQ+;P=gS>0>gnEqn`&eZdT5$qcU zrLHby&wn!&q@s~xV=OLXCwGZ~z)aem8b<>Ys;zlm(<{5Y?CcDXW${n06u`%A^;d3$8-vR+jdB*VG4GgS!rgm@9uwJTOm(KG%QIZ0BOn3hpmjjd?e@h$ zmL!^x12&W@P6ecBe4xPJnlK!`8!FI(kAw#J^5OT;|F^dxi7b1ZE^xFk%Ervgi^m>K z7uLhnga-BTkTEkpnuOMEB;}R+PE6Xw?+#ZG^GYn=I{CKZlQ3G;#yJ1>6UHlid;6Ac z&WBV(a$rBn!S0QQz2?s$;qZ|h?OI#Lg=9aznjM|+t&IGMCp@^8%8Z{XAI7vDWL+}z z3eyteV!pqeYCX9bN;pBj+JX6C)YoH9luZ46%QxrpTYy@8Nie?uO}tBPje)jm;EyKL zzi?Ez!X~+Q7g=L!OqBQ4}Yh(oA=IwM1_>uLVsPkilG5p6+_-@2(_LlcAda*Q%}M)+czMOW4$V;@B;6(l5R%%_L2D6A8uS~u?b>!`Dp7gV zipj!+iHV8c4Y{g9ceON3vdk#{7t4!u2 zL6J-yBX!B)zBgy>R?P20eQJwyy>lkh5+7nl^6xFIY4!am)n-+KM@FeqZ%WwnY|+Ey zZyBSk=-;#-TL8pz&@Dc8u&LE*)>E>@BaY=Eja!?Fq#b=D#>#zvPS@B?!rf+#H^!v) zalo=D!PuR}U?2adKJfdscs0>Iy3DT@BULP<0;MPYLpxUVHL!;)zma9L(=RfqNWK@k zJl#@7!0R%~sDY@VJAQGnXO`(IvNN<2T0b)GYCB6+n}#H&m);kA8eDHN`kwq<*Sp@| z{m;8^>?o+>SgYO0$o?NwXBie%|9yP}q+3cFq#LBWTe=&h8>CCRQ>8Ir{(I*Y&)gH*?~9_FjAK&zjwF5AS3iI56|??+$wy98sDa%*&QZ%r%UxiBxIy z!&X}@pp=KNI|?#J^33b*s36`i1aMHi3`dKl&X*2tgRbr__!DjouBWJiAeb&4Gvl?@ zyk=Q;$qE)?FiAj(nudZ(CG%OBMMN1lBG~L?+ywu6eN?&R6qoZDn6v+^KcQ912%VeL zF!W0i50DU3h*rwvw(*TFRWCN%|NVW%YGr3dt71ijh38{uJdf7q{Wemwy2mlDvTjd{nSC&pR(WYjIU_ZN#zXH)#= zk-Po~lkr@M8@QkBT7REeR?=~Yaaqo14rv)A`rnsda!sBmm^uLlC z^uBjrZcpPlmHV`R5m8-GG_YHTGHkB$Ty?ZsFVyB?Q;C8*iy|^bscazy&ry%UX4U(y z0|x%gq}PO`tLrU{0#?Oh=XKwcYS}ATo$B-t3=Jn9FWRS(kC9LMnv~F)iDAq7Xz7rg zG{b;2T`Rxli3kq;In4O&C?{9FU;wH}y!Fp9H5z^=53qaes#HY@KH*=`5OHj*^lR0v*QMu4XYSp_^n+Eb|E=Sp5on# z;35R~u)|yV%-#h<+aq^`WJ0DF!(KJ)hea&kH1ygmR*|rDKe=WB-hBS@9B$qYEv^DO zLlu=TfMAuKAxq3xC>H_c)4K@I}Xa@Bu0hjF2Qc}DqPU+3q7-hc~ zQ7+@1cqq3tRoBCY-%-u+q{j2hUou|0?7D6sf5~XxH5jq=7PflxCmC(iya@YB+wlRO zTG&!j{W3ZdQAXSkwawiz?jt}GD1Th-a^U=Yxq>Iu-YDg&Rxz1gvEo|P0=LX3KepoX zLg0>gCV!>N|M(w=UZ;M%*v<3vv;EO@zz^h(wUDn7*~Rr|4sXgcgR{hmm(t@aLipO2 z>~FZ~WgXMMjHDrUW`VM1nsd_cA>UeZGt-M5+|<7JY#Kz})}9E3hc4szm2;djo^{ny zGtjB1>Ewr=%7>PkOZew}wRsq5q5pbv z0nd;Gep(^!M+vKh)bHOZ1O)Vb<^GnBIvrlMcxOV9R>U^qwJ@Uj`)zv3t)qgKxH7{Z zdRATpc~kA4P6i&!7XK#IAe@)RnD59sE>vos@4BDkfE6g@2y~L`!OLN$>z& zZpoAUbuB|;|Nd|J(OUQ604Ae0q;@drP)a4F7Vy{a9pWGVK!ImAu0Op!T@}Z~{~E~- z{n)Ey^-Myd4=!O4*H<+vHL6C9@USu)Ug>=FhU73$=bJO+n^79pFEE}raUUbp)mlLV zK9T*JM_^~+LwE3Pn9&8Vpbt;+H0;M?Kit%#B<3bnbB>$OTanZ7Z5U-OkS`EHFCL8H zw>DD8`np^)wrkN~7HdSWMOk7r^H+B2b4vcybY=zj-~UOKx!T=XoOkQKfRJgPnpn)=&mTKHF6v0v61yLkjZ zZMuCH2h36Kn0x=q->#)YMDeTs&5r={__6H<0OptjCbcf$jFYko4C)*j6GjYH3G;&> z{na~xb**t2?@}jAyJmY0Hq&M6IdPV-4O|=j%VzI-xX|!W@~Nvgg)J?p2pCq|P-V-V zK(fi6s&$!$)MD0w;esDZH;ye=p}y>Gm&@{JXl^(#5M$H$;9Rl zz&)cJ@w7l-`^d<03_K9W7R+UAx(eH0`ACadLnaw2Q1RJ*%AcH)gSc?8aD=fY=1=2F z7r(K?EdTCxRG>5<9Dk09ik`h`0ah#5yP=5jXXA4Le;NjCq!qFT=o$s$75$bVs=Bq< zXLlAhkSr$ZrHHUF%2Er;j7B9fwHV2BUnjvsRK)M!zfs9BXZo}0Bfyy@n)%%-AsP9W{o!>9p3CDzw+ze z()0tL{-k56?DDF4sTWd{cwmWm8^jrtUCcT+U2+l12h-v`P*p5$Av(S%+O>ZA0m{$W zO%r|zp2p4^j&w*i&(;}sg^yp94NJJ|+1}ocjE)vpR8;(~^4G?14#12w32&LIm~xZW$Y5Zx8BV#k%W_)%c?)z%7cr~ZF4x%Q9CxhM z`{L*xvbSk%vzmW0k93=P`J ztb(To5}kzpO~Buwbkvf)YCnXsEy0skPrdGx(&LbhJBs2|CJD+5Y0Gmje;XPRPVs@M zVCdBgCl!vmYxclte!uHMr?iJvd1B$@^P5M%^@&QzZnQcq{-xnC6$_0Vl+JCu;LTPt zv%~APgVz_Y?B+lByVWN;`5b+G5eBSuF8H*{Gq+U%DlOUbH6oZ~BN971h|KTKsi8+s zPIgwxihjk@c3xfC%5w%R08h=^An;l@!quJIPp|!Lwka7Y?uC#2{4Yk$9p4n}4NnK& zAE{Q|_8Tm?m2E{7EPPs4OFw6(@aF=zAZpw9g~QG++BDu|vPucIedgFmi6BBPnA%#Mc<_;t;PESfC6-7UFMl zNM`wRcl-)=z0-Fa`&D1lwW()Wr3gxSJyxhEUII2FpWBnLkJa8#iCbG-nApmiXoRM)!Htgq@J6jXl8=^_G+Grpc`~{A zXzWBBBJ=zI0{6^+ez(Qwx%htSRz}5H4Y@mx%nNDHGl$?2@U*c4Ni<;t13E&J$l0A~ zUlaThIL`5C(pv!yX{fh<`TqW9889q0HjRJ~qQUE{Xub1a$$D#YzG9l8xc>_0My@)j z@b$vH5JE2c?)bH`Sa^^HAgu9wb)rO>&`kVnPJBO}mi1>d$GnBMiG(N$a186MLK zdRD3ln9PhQu$fNj9<3B5AfpeKxmj;Ql6TZTF@m5y@l-2zT^7X$@(s$;lHUx~Kjh%x z6^`>J#&znWQ<)nV<)p0e6FRgti;CCZ{|pw2M?M)0qaM*XCEm!cqHQ`^kw*f95Rp*a z89$ygyh8+;aYmbWFRf+vFZ@vUdiEd24CdPPJ7;MFD5*g&Q)~F`RD4?Ovy= zt14^+T1{IdMsBNR3%KBV$)KEZ6fF%+KCnry*Kyb}l(;;8Cl(ZNGFPg{ z1c0>DC%kT(qHVj&xpBe5WT>Pwf+NI2F2T0X2)@SG_ni|r!#{pYU0fCNU`~=5P2%PoCl){#%=%t~$JCythF!$*a5hI65tV zI0mHE7wcN1{{RtIFGdw@Xtnw}hYxd#bX8w(=Mcoq`WOy1WO=WsqBUdd-?0oH*5?eY zoVz9JCvI0ec~?dvCWu4u*4Z4lbP1;1-}-nGM;F{{tOpXK3$FMaZcThXGib)BjheQe zlx+?WQ0gt zb^7QlHIkG;;e561exOXe!Olsn*YrgKe@T?_$~g|4e0=pcw}|wfatB3xy>Aom?UC+h zFd$V80p!S^m90--7OCE#R%<$tO4i`R<^E?18$uq0OqZ?i+>gdi_7E*ECNCYqp&oJI zg|sCM|B_&pQWICGv~K$(sogiexRIH567$@mdhh9dZhVL>022`WO@tm8Pa;oApMnoy=i7m+l$y8mkvUx(``cq=Z3Jku^X2I#av$DigeY z>@SqH{EJrvT+8=6qM$?GMf>;8$3vIyP0+kClB3y@nPUr3B;vS0Pd;!OsrPP+YR?i zzQ$>q9bRr68|xjZ8g^RRjf51oY zCR8Sz>RYhCPKiQMCm)^0ErIj7c~O@J?iBkiPd}LgsIzXS9fr<&y6_EpoCz90urk|B zii3SxbrZ9sU`pP`urcl|>BA0)Oxu+qcn{Xkn7_tU7#K@{nG5R4vjTzVK~J_64cH8;*lX?U%pd zQ5s~GQHU)Yuf4pFSF?Ka%LAZ{t(X9_mKI)aI+SDqEXzm++T1 zSvs!7*8pxKe@Xu%yxNEsrtKRUTGb!LBohD{xz-D0<`AW>v8Roi_!5+B%F5rq1X>db zloP}JZw4>d!=$2Tm=*kH$Pz_N+#dOjCs{=O@J6hd;V?ajXG}=qT`%jJc6%(6a{3=F z%5E3FOz$p)?Tz~-`kkBS=x8=Ghc3z6dugLZWy} z2Q|!0f_=m{Eoxd?@gV~7CYuKmbYrYDq~LR(rWp@@RK&DNqQN_fc8&yA1F>4ca{_C+e(vWukBA5pUo2=#Ymj-@YBZ zC%KO>_fbEd9P1&gUNJVE?78FL30c%cz8~x9emp6k2Eyh^6n8$0VU|TKlIb~5$Dab2 zwkfG<`W*-sCN1hoUHlNRq!-*75bHOLERL3Btn`0$YIrjZUzx_3`_LWl?g^?IR{scW z2Mqe&I%0P@FY8e35dA#QVN(KuE8@?N>)MdzVJY^p_2N-=JrdYyE~x5zXDA zabdp3QksF64T2W4`Yf-tRX19`coU8uN>6Vdz}B|$5@xQ=m@n*9g_-IYVm9bT`mdJw z)?2b?`pot$_iPw5(n9G5s0Yb8_{AMY53m)d;0;C@6aVRC=#;0jEIadc4n7T%l=TM^ z5(X3SWa^<-c`N@tJjQeQ{#3tpFZoNAK)AaBMb^yPG?aa9y&+L`C>|4C`c z@6RqKtN$3Gbas9xv8{P%-GMeEQDV4m!c-1*?xq zO4?0bMPo(oF7=4BZ725%`I%9res0?0o1iT%C4~zI1hEF?JimHkEsAwd0@ld|ZBg7t}cokdYB-d_6G#5h4ps8-<1|%_~71M0IzP|q>LRZ+P{en zAe0{U22de@ye*q>zufGU+eClk=~h;$dCoO29Mp+e36xVR3je*M^gW;3WHfyfmBl5* zK`TNc3`rkQ?V6Z}4%W+SJs@Pf-&*m*s2^aK=&il>XA_marY3j0(?#C+%yXW$%P7B) zY-~xnSUfY6qvh|$tWr^}S<|PvQF`Z@V0y^6Vhn4(dK38N#5aERJ?KC0FOFNyvoUwu zNF{x9Vzd4b?^*3raZ|iO8sEVr#X{DP9Csk2Te2dV=-n0~q#L7`G;pn$s4I@}xAr=k z=Fy;DN+tI<#^V561!+NTNHQttnN?Zs1Q#0)@;3b+yAr%jbG$nM!w`+Ii5<*3Di~m7I*r=(j|A3wvGI=O)1{~ z?Ch+23PYto9YR6GrP zd6e;YjmsS}lg=%t2kAng728B!RZmOLqE)OM7y0AZ z+{bvkaCBy06P-&WUhgF->+~6;b-3jQYoz)pBEK%KPy8Q z82m65vU`J1QtBxIjNWdP3~1wON$OKXyUt~nc6OrEO^rbz_Fgnf%y%8K@W>;?(S5HU zx&+{!CJEjS0ST+!=97%@(6_$Rx}0y>-AD)@-tJ{K%1Pg#k7JgGc}Z-lW*4zF%j)m2 z&5AIv=)u3Rs6LV2 zhDyU2_Ag|o*7F{3as0*!m8j8rGD(z6)^Z#9?OD3vGwGQym>B7O zqZwQtdZH7}KUpN>RmIaI_gUE42b>7w&|xPpe5`F%7BkjM9{JJeB<;kIe)%4eWPePH zed@@BkK&PSE}N~JEN3^;Gz^ql${6bT0j_>-pB+~5>5-V{#{EmmkI=P2>$Yvhhgala zedJrM9b0Oq`k!&5gsEI+U7BvS4D21!^B>4+y#3Umu3dLt+lj@MOhGEq_mvt%1uJax{JoB*;;P>l zKfTd_%3Br1A#sA!u}@C zJowZA6OQ%2p^5sJovBTeJCgRm-%Z!Ka3xGPkx`{8R$T!2%V1vOe zmuIkHa(elG+cYvZO7yc|LwjXHNZpJp^T6e%526cwZCi;$1NK=q;lqTRo{?4%Rr{>_ z%eA8c>w>0_n!!+24Bx{#E#PD8oifYd|MtResd)@Vqdg13^#)_NdlO3NrsW^}u7@&* zIQ#2s3Kf<8PnAh;m%^St*2FyeYZ4*1j~LV5<-Fa_7RLo>?%V2LiqVjn)#zH(=RA?m z8XM)yDc){l^lco1%egl}sjpzfOHwuF(~mTXH5eYDosRGhHOWtUy0;|p_a@{=K(ai5 zDJupxfk}L%1%wMhJ%D4#vn?RVV~_bhQ*H;27XKZ zPC+Y#aqP>1iHjfhZGqmSccZpY{>HoN^Eu8?{;=k#{vQdi2RkOk)0t<}6Sr^#7U<8M zP)OainjiO#soyPR*0%e}1AQ6E7wdG8%g?)4WGN`K+#}ys!lZe@bpGPQ(x9KP)wXKx zxkvC@a3STeaTiAPpFe&uT#wvG%^LjV!tauV1();GXKvXV0zet5d0MRZ{;2?viU@>! zK1c%@ZT=vA0AD2&NPG&P8n)GQta;hc^EarzNI5rNx88DlDo?`avx zo#bH45m|Dv63;y%nZKJVp}_S|Ue)kL0 zeT(eA55v5Pwc|=XaZ&O;Lio=ZKOwpL{tKNqt-1v~O3m0Hp>tMxM&^Dj>H++HT#8aD zO6-imQ+pGF4IBX(BdsnL6{7qN6W8)jlE-8IlZ4=du2)X}LrcTNqguS+);=@c!+_;j z=vYhF_HEYT0^g`*#>KU;DK9ske>ry7dYVcFkP9fBcts{ru{S)t zSIbgXhF=e3=^Tgzn^c4b#oLT+74M_h3wZY}YwDHYZ7+Qc`|094G%7`Y;kIlnPh73^ za#WWt<&}T(?xp;Efa*EsnOGk3aF@jo%T#5Gnwo@K<7|v}Av`k3I*)bnz%)@sx2W+` z{RF>){>c>|b7nzLrAjKV(20$|L^+Y=EURIg24tQLs9N#64odPxJKmm&$>60yfhi+P zJZkdFyWpuWkuI74hVe=-H|(c~(#*18{{78%K2#x9xt^@DV5@3b3M(pJq;Kn=Dj zVv!Zt^2`enHu^*7X;Qv7wpx7-^Qf7pT}#BjZRX80A+QxeIfIvp9kH1u6_$LQLxx;V zAw1QDt&kc=h=Cs;g#K))d&OLJCODrM7;qa;RgdbtA1Dg$64D$Ve4`z<2a>ag>&hl~5zH;JSR=gn{~lslLX(@b)T?3&7WJlM&5n(Mmx4HN_rRuWTEiu|wXckWK+6`BEE?qugTQyUWyUI!_v zs8C$oS!%GsS*SLyek~am7S_fFCJTHDaz9--4qkd$HQD=x_PoP-mrK1-s*L1|&Nia> z6b0e`0-|u!;?mJ0oF|F0=2!7{{!D9Aa`SH=sl`J`M?dkRh)qlJdJ2|&HXh`f-5`Hx z@%oyXld0)mex5;=dDlGCf1OiTz$jFqY>$WHJ9V%Q?r*`W)a*~it>m#Vs01R1%9~-) zlU71OgM089mPUpO>bXFj2)@31j zM_T6K(nr~6=oP{rzhdNjZebZd9GiR)*iCqRZvBDt-SKg6mypO|%m+_^I`(?zBpWi`iroinAl=43 zm6b6VP60JL1+YJ_HBZMmqaDw z3~ZtLw>CCvP8KB$n#n4*Wm6SUc-Pqo#3I#N1lxOKOF8P*!tLI@r@(oOd>4u-j+n0a z9=cr%IkNl%zWYJf{YP=g`{{D`b0A7#WCr)BR*)dQ!n@M_1l`yRSK8&KBp>Ern~NKVDrl2k*oz=aV71F=21R$|2XkiXRaGv=dJV_=^mt>A9hVnih{r+l*VQDXE8LMg2ZTui_&zGBR5r%+G&jH8~mEum_jo`FfO9MnWQlWkFun zqigA0R)F$EeJS^T-{XLO;?bh}DRm(GqBbm2f}otni(U#!a{18zTmzh5D^Q4)Vz zEw=RqEVMNhSekJbxW1epd=X}L&@JQ|yd zk9di1=KxPD#aH+T^Lu{&?Ni`}_=JbtYF6`bD+X z27SQOm9=P(Ph!m3>yr8TRl_j1dC|dGzIXHsK_-UbsoBLKD6LUHM&L8nheopByg1Bq zJ(15r{-8RZJaU69ri{$N2QON#7%!1E-TE3Q7KM&xQ=O4!Jjznv(pBB6<_FTyec}3z z5c<{CwZM<(8O`i>)P*tJecb_$iGHk)_8aXVzG^u76PTNn;NOWnD+%83c+QI&VAO3X zvvJteca$Sh9MWBv!x&yGU;Czs3sHQ9 z``^jH6sgsLK19Z`qaPE0p+zj%iqeRC+yDEtM&)!aTB_y`<;p5DIEA|+xYHt44#FMt zqb;(u6>&p!C@{l@R4abp*q3Aa%)I&uF`@g~Jj+(-#~b|_WkI`$+k^w>k{9LpT`vQS z+2lTxO~CH5TWOHy2M-mDtR{Xd>tVcC-mqI~oJ8<~LWHE)5}r4&giNqzE8W%3T*pq& zz^1bvV+|Wh8u(+%nmUWEd3@g<>{qxK1Kk%xy#DMz|I%u}_x+;Whsljd@t$b!w1kQ?>R?H7XVtw2puzpIgq)vyb!kSwyNZQE zdAc9Q+qPI?$8~XvKN!=WC^bgw>~YW|B38Ma0-Gof8Omtwtsh-RK)>piu#wE9-dk{( zQ0BKYjh_AmG3c+1@FhP|PAPypD!#Vuddsp29u2O@Nt^7ENu+ClkqElI2a!MK&=I|& z_@vf%ScV838XW05FLx8tS0sChSiD(b4^WY5TH5iwhy=~V=4kMve*G6GBPZG`{Q;O{ zdMk+x`+{XIAd*GllO;8BTCJY$KIvso%iTa46mN#z!ZfJ(FxvtJmLa`U1w; zxhS}n8>Ky7q?D_><++k-A)r40P2Q$j>&@-HV3S974}PEr+DGn7F}x3DUb)f3N$soY znBr%c^SeL`Z)vFX4j=k@O(+I3idlAXDHVcJX*<@A32h$BJb)xzIh>e z1kjoJ|4w#t_Y*&Kvvm^s)_ynt+1(VJB^;=P>_jr#*hti6wJ%D}2{)~^!U(5%;N zyZ?9k#1+hyydG{o#hD8aey|#_!B~na^+fN5A^LuDMS zA9MyKC(_gSccK{ZH&@&G-4Q=TvaTm zf4vC#!%K3GHOnb7Nz;}W2>S6q>bpm^8d4RXOvoc=IG%Yysu6ZEg4a#(8EesBxBxaQ>|C zY39GPeI3bHo|7Z*^L_PeK>5?IRWK^Y`?`Zle>qgrtiq8f>{04;Uah)g3v_s_^L-Pk zipvl4yWPg2m?Zzzb|ar$AsPnRbk@iA18$kHNYCy7il=_g*qmO?0q&SMkLBMqAjA5( z#fmsPJgm)*>~&b;<3>jXpN6xd=*>0lkAu#(1C_}NY7Ex$kM4KP+xsMU+d+++Ls19o zP3f+x%+Xar7vJ1p2EOwj(G$GlO*g?P8Ni0&&G4>06ZG@&8AAvfUZbMV zj&s=tQ|O2B$b}%{fdZDWWfWLfijQs%JjRAk6`Dv~`;PT=FJF&uzbkH>Vdvry6gBOV zX`I_#u)kO~_4{?2?D&c&{g;nK`&^vl8&KauyUQ?6?riSZ2&QUmz|WlkotzGe&_tJ> zC+1}*hE$oTE;K4mW9gE?k1_)gO@^YLk-2UH>68FmnzS@!`y@N21g?>i;P*)*YYf)} z5`7_E@Zq9?f?Z50JYz+)p#@?8tK)F4BPuPVxzLEff)SoZcRYyj{V7}*I`FDI%An7} zw@vPf0yFktn`RN#M_;w)VZ_revoaI9m57TjZu@lz9BJTw1h2E1L^AV7c_PqjFyyIC zGyc=uWO+_y=woY|J}1$9*muNo*WAn40CobBzOU^$gRldMshzSb3&xEgzFDnTcuB(4 z^`xbE{PbUEhDO!vCY5wAEE6CF{3Bag0Ms$lx6d(q9h&at9s${(*!F zXI-m2ttekjiX>Lizji4p%H_uN69~VI?h6GBe>j!?`tZ$Zx0Y+?C&>r4*!M{T7#Tkq zJbG%HlI|#HMyZglom52>MP7>`QV{-Eu^~O|-X%6Vo77;aGKc?oP-dfTm}@rTxO9N` zyz%*poJsjx{|?`nmC}=mCZL8w2PzvrXi)$j_KS>irB&jS^YSS9N-vQVU@vlynq%;c zL(Jcb#GE~h8P_)X6Hmnq`fY}vsU$O^P#wSQuCau%YQEBKOuUm2Bo=79$m#WYSly?o zOJ|QM$D7`<^^f`$L}I8`2VG_3B;`trf~<6bucp*I)k0*=Ih=Mvvn2uwO=%Dw_qVC~ zs%>F6(CB$5RwFVt{eVQbAjm|ftR3fdI8L;KJ~B8fL*0i{Moc_og>MklQzfRB(c+wQS8B{Qa^L^m|e)bgF(rq9`i0YzS*G~Pl8!vo`m0tyGf<#Dm!j7`t z5YC;CjIwO>;p@%pJ7e0{jqkyQM(TQl|+!B(1${f!>}xz)3HFI6_Pq{!+ch`^aWY>81_`! z#zMJpe>fq3ho!npB*A(RKCiQ12tSZ!NmUVF{JtBGlaa{z_DP|(#PMbHP4re++PlbQ zKQn=g)$2r-6@}`91>-LXUHcIwbm=MYmoOm9wCFFKCyID1)-cFgW~2V3N1t8L7r&$| z|Ke!qfD1B&^OOORvgCJ;!?M9Pn_{cYy7NlkZo$pF7?XiG)#m{Ox{ADXM1rL|2s3XH zDL!3ugmR{D^vPxNC)biiN6dY{96=`7=|r3k1KlZ@Mm}I`f)*1?{Ru@A14n#!93m0A zKfxfoqjkA#YB`@3*|q8!l`GsHOR+f5`wdvSZ`yVtN}sr7MG$tYYwx+$wCgq(`$xj@ z&l%sbex)U9+ZkqZAW0xomwRetCJo``WEIO#XlSMgjivVsjsDk~p#A!>^21Cn{|8(5 z+s&uF*E)R9zkzg2UQ0Ut(AoFf!nN5cOmlY5Shw@fw|_htdLih7e|9jY3PK^UUQV3m zM`!>XFo8tJ`%%$?S184G1$mXm1AWDm!MtK$D0Sh0gED$jwXrAeCm!iEn3_Q{1hEuUWc_(!)r(((QMo z`EcFXNdThmHkm)+rD-XWdmtTJ0gQNI4UXX8&D}lHzrbI*C zuvRTpe!Tv*5T0}oHbZ;Ae9rOfzRF8z*~7M@3RP_+6v#8wLHs_viY1Vd;$;mIMjcu` zj=CGoB2h-9utNJ^DY2X=aSGFn8z`c}FqQfT6liU{--KOhW7VP4g} z6D;qyQz_CbrLb9nVf{Yp0>qOZeP^`LUy2Gg>xvJ#%KkRy)D>vr6!mFi<6}WHiyitY zC-%7#O3sBE#@*MVi%i5CUL|k*y+}AfY$j_9Yx^Y`p+GQgT5PlqnN;lEkpUe zDmgpT z3vaV1VM;H8bo>5__b8j?SqjtkTuZ=j-iYfj=Kk4v`t4M*J{UFa?LO}IW0>|%xYXj0 z{2Ej$QgfR3cX$@1<&cCU zt{wKyjh6oVIs)C)uOGwzC&dsY|C)DV7WA_%j$WtB)ZUeISF}<{_L4hv%k^rkQvT3= zdNq3A@Ak}RHf=-@jsBw*8c8aEQ8~|f83JRoWw6ZevSdHtG6*G(9& z#C|A@@A5Aoqs_S6nfissyU_A_-QU65Uf@gog)~sbif@Xh76-fyMXsswAZ5w+rNCPl zlhSl4?5a+hA|vb}sosbw_7LImt3tk(zv|_I;a3^lTD4iTz8|o^G3fe;Gy2FB0M4-R zPcE;r;FFu;MtRUXIR28M6m(E$--TeFB8`1(hJJVHoL<<~I;Kd;JW~|If1tisU%vH4 zu+ath)&rei078g_{|KfHlpgmo%ydxn?{yI$DG2#rZ9^qf2`?dke@=2V4L=@wl)(+! zpxIrnkQw@*;4PlU<7B6YuVAa#(dk?3G1_@_KFPbfghS~ZlNOlooj`i(xlx@OlO5|w zSfK2zUtm=klgMBe@T`JwR(r-|Lj4m~_K>=J8&kDFn@v)xlgk^vdrk}5%drCexj2lF zg4Dbt_Ig&@)XInYVqPKG4?5W$_?z{u6xh4Dk)T=8RK~HM_BCo=$+&jDr69XX@yMkK zF|5~jq5>Y0OZt$H9-}m4!+FaMNi#ALcaH9ZTE|tzT?KC{y0%Tr-|i(xcGoJ3Doy`u z+d>uf{`U%STz`pH?oWHGRP6bKNQTJMe0*o|bkxx`Pru1+rY^-^!Yno230HgkHghGx zY;ro4ec>qJ4=DbR^y++%*bq)II#vF|So9kMzDu*L#Tsl)DO^4P90jTme3-JkhaN;Y z*WEM-(^txl7KUkhO)5Rdmuq$6!$PgAsrA?1a~%5@jrl?~1-|O$HuSM%ZfK-5*l(b7 zi+5Rc(h?7R9=FMki1i*fZU5%Kgo?Rz&RDn>|H0j&Z-00J`U0c#o`kis5MW1|;y$CB z2aErE#Kmct|99pQE*Fc>9koe{z2}I$6(Ai}!VgrLWNS9d1lfD<0w3S%dYlu(I*@WR zX8of2tT)T2B|0lhB;uGo(e!YViHo%=mioeU2NY}Rv z;Gf=bf2K#-;Awygmd01Ddaz#joS?KZtB1>eWi7iGM4c9nu*&-PswPGug!%scLyFRp z7I@F;{BGMxvjWo_>!EG(5-rV|u&e=@aU-TioRiAa?2~YbFnIzDb4tpu%M)c;L9^L$ zM_f^0vs!g^jWC5ng8~$=y1eae1;k)_dNV2&y<(Wt*SKdIyi0Q#NR~3$iAUx?o1kiB zYoHZF<235b-8C&a!|k!aci;nRE`0@a?#J^3$K(LEt!e#P`wFi_LBzcVLBEa+|8|yj z+2x*cHAlvk;SXm*UFhB3PxVJcBfsC-)<*}1ntqk|?{V|_?{TB7H;kTy`nlyrf@MBl zN;?cz{9)D!d)$6@!@QbBdf?ul-$zSR6T(nBmtmWpY9Ih}kr3cb48kmJb(vYzgQ4ED z+CTF0g{@L}A7OKWkWBP#@a9<;wknMR#&L$s54{CGByLQNY5p(-v*N1ajJgyehZ@eV! zE8al5j$k9K*vqzma(co0m9DemAcCenoYcP?gXtPC`acC03+sZ&bow3SjnCAK%Wv-4 zrRdE4$OFm@y|AZm{40c54RxRSSquY+z{I-6${GUGnA2QaC_kzi-W~E(3{clEnpj#$ zOuzvHd`QF_XEnpG4z!-z>78~iW%Vvzor?JaZYRhc$G<0c`Uah(*$B8NfW`>Xslhz) z8)h!%ri0%l&i8e=r)>|1x+_!1;f6p~oEe(7bDHE;+|`xs9gv(5=^gfQ_|?QpVjTnPEO{#74t<{0kl8AU>-Wa zP==nmj0h@9{Wj)v$n{{dTZaC<#o^N;5>TW4#g~0Mi z4Qm1qxTse!ET~sT@0N|rTgbwpxc~k+#UbjyGbAx8=EyjVA*D>G&@3tXMpIE;wN(7u z+(7p}(t3r=;3z{^m04wUR3Tgf^G+BurwLvLiYKuj(zFiT%WjvGik$*Ou#5act-?@e zc4B&PX@II2{D#}^B4!l&PHSBEbp6yY5vVp7C`p|FEnLT-`9(l(gobOv2*@4d&racM z*4<;F$zAK!sBh*~OqIifqd+>WAt-^4H9fhims7r$PihT82IKBqtdGJ0%vrtYH~sR{ z0+LhG%24E#LFlu6-C5^1o8wafQ8 z>r&yuYB|U3u{Nc()i5gQ@w>uPH z>#FoXzH15Z5o%fi<=u_Az<~uE0X2>@_+NE_5H91PQx@3!>;A#V7s0qOmN^>M<5^@z z4%mm|%a2iQ3-v+VG#lgdk#49puE|sHPfwMy~?G z!X;C4(HV5o^dk#5{?i(~gb+0^9oJgZ+>H{Ud@dRy*Fv^nc|PEclVQkRZI^lR&eMx?!{7z(ip9%YHg<~XChlJta zOH2aIrgsm9VFFcDtbX-9LRRw@S{rlxWTO%SXv3m2`w;59{(f+CJ78)e@}Vi%-wcwr zA5a4tQr3YTIXp6Db9eW7tMsnO(7Nm2(A~FJH9IVI!HyT8_h1sI{^?nLB^*?%0bzno z!^toC|7t!&zKA?$peYDdL>+iM5MmI1(~nK7z44xdfK7jJvjlT8sXHXeKaho-eqF{S zYtl44|FyNPzz&18?ZPYaN|LBdlia$EysAyI9{uVED@ijfLD266tho5N*(60?2tNKZ zVbOPGDb*HCDr)SwollGZkEg2)sH$taN_SsEO1itdK^mpIySqVYE+yTdNO$L@TS~fH z$xC;C*9YJ4-}!mY*?Z4gv)1exI>H>^~0qB=S_X7Yp$PQw|Sxw6x!4tHwM%s@*dNtSGvJVSH^0^8qfH&>_TSt90KTku@xwk+Z*UI38QZhJi!pjRQ;gsn z3i6nv(;y@&GnY$%vjsR#Bizp&$pcGI=gLIF=VDF0?B|19Nnfl!s_KPCSyT)(AXj!J zP3c63yro)k5NRRw%|zROByg$|H7=;n*KU%bf^dFrt17ohr zkMmk~A@XscXu)p}+a^(ZoLFvvmB#ep6+*tp{I-7DVPK!l1xOW&WwG*Yq_-W-^ zBZ?^|oR{ZVOiCl5w2wUo^z@%FsQG@PKHISLTSKbr0E<6jd}?esi4VFo<6NYK)iawCD04C6c~=ngA_ z+6%-#4Y+3b)M&x@#+COJ=J3D~#^`^&rr3y6@C?%mLQra$Bd)|4>i;LS@jSyTBkr&SblOcaMMN;&Qj<;+M{q z_R!A>1NI}HVhEE|eh~ZL*QYuEJ@nDUdHazQAO+CvJUytSkd;0EB56TSmk-bNfJM^( z=u;Ao#-X@_rZR<61Gv9rM`(`}EUvrj44H#kIm}>;LiDK8zc3!e-#BCjqBAjiF=9c> zSpxoXtztvUngZ*?sOgFcpAGCXA+I+OhpyxG1*NB&+FX&BFZ-b9_+8QPdicQS)r_{E zAos#*sc@k4FtwA66f#Yn&~dQMZhqhU_6`O3O@zG|`Et@qZT;A5mk#8z$Cb6mTVOfU zbXlJlXw~Ix$S$gqW>~mhWsBPht6A>DQu_1V*RKsn<<_Gk8WUHPQMmBtdcjdvIry|^ zR3{7t85Y8D%hU-EA-@srDh@wM`j1gvkd7tJ2;=<$Htm_IdkO+^d4VC4j z89mVF%96JfjzrSxCTK;z-)6&7+PuAEtWwn%b2g86%17a*u!^B#HuOHb=z2pK~2NHec(!utD~t` zy@z`HXeju*!=3;8j8vL3XaVtsPP~5AA#tiTK52M;(jDoraXq*p^Q7GhIFzhVhg=|8dQ)jwvZv6&a>F#j6C4*KqZw{>QClGCB_c;4OF z$FO{?l*;sk3hmT`%@;jW_3tWab~5qnCsz)i-~V}(WWM^ zz*?kW>^4X%1yp}T0s=iXEqL0s2aMHSzPnN2Rg1Vo#rx6fM_s5kHlGUG2-E0>utu=(iYJyrI;7jUPA^@u)P?p>=-##!)#@aGuFWB{z1 z9&ge9&aUbK9sS8%yHn-ds0)*nSk1U$q4~IG23^SK&={1a2eU z!DzDn&dftr4fg$7jHM3?FFR*}eb>;+6!K=D!g9-QeF54Jhp%zeg;^}_Z{BBiiQ$+T zSJKRH-*5D`vhy^t`93HvTB{y1Q(wq zk6hu3oIihY;A{j-*xtzACgYPP_F2x#rlUhrDEA0SIJOFpn&%K1nHxIwPUKCMc$+FD zRr+0HxiKi5UCnIFMtzHjS-qd5RT`Mu|#H5sUnVj{@v42umHEJk#8cqvY z_@DOxrxV{QUA0$?Dplk4p;_L<<2gT=2F5`T8cLXU#y^ot~aY_Q!L1`&KObOlQYRFx7*wZnv;OvH5~Wqlq0X;4K(nHn?b5*Lyq+)#h%ooS8HcJn>-J=bGwIu_8REbt0QPcJF4=xy{FpE^Ymb zCTF$zhV1cJ*|7VpkoaDeSi4%YA5UEn!QwUV!AQUy{m(dZi8EUY)avgfkFhdT<%4(Z zIFN7l>dz(HXnL{Kt^+k8rSD&=rVC!8roKR<<#;LHheof`hT>4l$lQmD}2dc=Zbht4N-{jhOS>#ExCws@YtwV&Zb1acNI^q60;Yzde8=6J{-DT75F(VYe(_$Wf3hCDQ!X>HZ}({BQs6RY>dbi7^57M|j3LMhi*KY=brwQvbuM z8n?AWBB=)j=h{tL`eI24(xZ_Wp468-Qh$9GjvMBYt%!(VcRe69&LGmVGj#y{Rz(Os zZ*SO2VT-#A0xkQ{h%JJYo60ZU%-XWkv+n1YV}#9btz;`fC+&7yGgMo!^;*IvyHkFq+s z3BN=Xfn22GVg2Di#Go8 zpxT+PLdP9Dgb+afGJ)!AkZ+No_V&*O-YEh6gh^9I+i_3)R-04|>(mUnw<%+(*DRTk zN}tqHCPWqc?TCb1CQDLKxEWQ?5TY5ch9T`T0$jfoJ}=krviY-Xb_$+tke3Q1Nb5CK z4sq+Q+b3Htr+(~Fa=a<+MsD4xF#qK^67l6|w`X`yNKqrOaCge#w8vT$I>n`k8EQOM zf`TNZhLaVCU}m?&%WXB#cz$!2m3Jnb5rdG30QE5jc+yin@QTJE(HJ6sKO+J8_xg;j zI*63{rDINQw12tsiAQ&G4YiKe3ayQu#{px~)_RVN|#-sXcdtzevWy)r5n-oPJXg(hAxy zB`#0i)1--%Ua1)(57<lW`q9qpno|W8Q-f;pFoIPcAEv%DMEr|lstNmbesx&$`hX_LRk-_h!il;04BpL zhnKS2#280TxG3?ywI7i(*M(>@Zy-iS@zF-OdcNl;kf~DHR;b3=3fuJ3cmHscL7;)8 z87UanAh#fPwef>$4syBwMfWoi|K8C6WU8Q(+E}(UQhDY*<2)5SO|K852Q*9XLwLIp z3#FoHrpx2Iyh$=5+of1Tk#mBTi#|NJkz&TL1h#?YTX6VuMwwzPud1QA3sQv(hwfeZP2BmbwxquhB7qF}{89BXKQtj$#G6Wa$Sw1O&ch0Qq=VYv--&d;qR$ zps-;ncsr#V6*JLXd@T;y*nN_aUxMY)Eq1BoeYVHgoj&9en_8}Wsl*=s98tTbe~pnF z;r&OdK3n<03U@y=0mYiLNxQPe%DT*Ya%0r|s_X2>+!jJtv${5yUADnh zTwSV$dq8iQ?(pLt;a-kF9ghtT?0FG7MT9s_Vz{0W3Y=}~{p)33Bskz#MU%kYD*5j> zL`R3xKdVc{tA;KC`EI*11AwLH1aiz5Ef(lSIBC;$T)vZP@)bMHai2w^!%E6Ff^PT9 zyM9YNiY^^#K$iGRS|L^T;3jLX>yZK_Q|3WNjZd|$=s|yNw=BML&BCP7x+S`O46M>q z?ezrw?(=RbdL=Q0OL2vdfyW#4TP(ZR{S4o(z4L6{p!V@ub{aH&`AoXcDWi<(QJ8RfjA+n1y2+r%)>RGWPez= zxj!PDD=bzyfu{mxjDv>LE3|%NmoMLM4Y){%@<)JEaGkSo>hn+^QKD%YKX3L) zZVV=gJdzq~m&4B7r{eCH3TPS9gRaN7oxUkaMFPtes%dCV5-;+A^6_r`TpX_5yF=(L&5`nKK3tvOOUGm}kfsYDGp6JSM1@kK+bs&3UH&*n4y^*sX zw_V{wG33J!LE+dXC4@gpj^2>?oGoiL9X0J8Lj(0@JnSGvn--T@dCQ19(Gnm@Uy?aC_yKk-U6n;t%z)14Vfjcy z-u0~lvzf&>$wF2oi8~sEgt@H;3V^J>TYR4%`$_%7Ho0KR@u+J0+{+ByhWMZqxf5Ai zvsbzEtIBTa*SaltFc0^<`)x+o6N#)HeIqZtvRzlZvj5vQ^eU+^o+vekk7o%$NVL+D z!cH^(ca%bcUYDJZJ#$~AIL)@{d@K2+zkp#Ky>tCnM>b_cyw?}Y-}Cko=GxF2Og`8K zOP37lA_ZI`(O)8mLx@x{?Ucs4R9JKbVvT){T+E`f-&Yir9A4=xHss2$z)^$yo+dLy z=ao2bzWP;~@~CXN1<0JkAlogG22?FJm3cFAq|zLd9(wjciW|M0jykvh*xwi#Rl^fZ zm2DXS;)=DZwu*uO)0wC#UnTWXj3=-SfHWvZNmH8}TGQ~<`FALAnm)t>>dy!N<81b@ z3jKJoP^r4g0Z76tPRVX$uT*LPWBNIdFcF%Mnoni93@b)TuYXfdfgG%+S;tVn=*SH% zSov`CJ2yvAtWy6@vP+RjnP$y0Q@^SOJW`^_Bmcgr2sMoSX~FlB3RJy6zfgS`;C9nM zETiv@4|4Mw!dL;g{?1rPOfjp(f)w+BIKA1M8J5-9084lYZ1)F_oZk-a< zIhW9PW(ct7V94O|sfpB5FM`Bi1QcHk!utBPjdX z=r8O!833xiZ(y8j@n=4&J;~02gG|jV*ha|ly6dd5e@V2m7Ac>Q`0hQu{O5VCd`lZ} zsAi|>tP{Gja#{7Nh5crHc=e?RfLbr>C8D|8|3zGi=gU|BDn(G8Tkz`pdMXq&d^kqFA zN)4X`v3N~+;hyw%RD>HfYp z`1WwtMy3>U#93|c-w`>k9H>>m3>ftbXFUzQ3DF`dK)7Mw+|8kwFuem2Vj{rk&+gXG zN$T8BizL)rm8m#11(Y*7f@^QM!mkhqbQYBFvaI$G(_wvS*hI36bG2AJc!DL`ZJewS z?6U_Uej_2IfE-2lMmTmnXIjam9jxAWFNRNYMLs2hKvC8~5Vkt~!GYpch8xm`Gz5h_ z_6gJ(D=cLM-7YCt=|&o{iX4LP6&juGMv}hgYF+bj()&9U>wkwC_?##tlLIWEzczJ2 z2z6D50c*Iq^X!wCWhLfMo2hT=<5)5&Qu~Xmc>eq}0mJfq;PK%6j`bY}nNZYItonMw zwe|3L6ZUllRGbfUwyIP55E&H%*g{XRU=kdI^K$s4tvQ#_{(My zUinu0e!GRHgX?6Lr0s$oH%SW5TtM{fbHzwT_&p-n@A^y4#2j8&*!|?%t?{yw+vN##sf{ZM=W{8B#c#?3$!SDsJzOOmEAN@sl*j5b=h5 zTq5#Lu5f;~B@OFDs`iKbsV~^wh~jfzAGFL zvX>8N{-FQkn|+GAcy*ISK<{@(Q>rDg?@c2Lp6{9o6u+!1(&m2PH9yZB@k4WW@n=jf zxN7zo8$5du@ke|LUX9cjEZiD|lv(_X`F()bOdO41&*3whwk?t{4CL>^s1owCnp;pH z$@@a8c0^f$MzlfSe6HY4ZTJd*Qqa=x_j0N`uAK*`@z=>#*-F<*Qk%8LtdokeVz`u% zUyI5+T~pvv5_>S1Z4@+`^c3}$3FTyw0N;<^4EPT9s&QF`mG`KQ@{?-*yK7AXjAC9X(>i z-ltP;LiR6=_CddLjY}9KvmAJ^26I*?R;qz^BnUKWzd^;&nO6usy_+*tcaiOc6*^|V zUyc3U|M@c(KH;YqgSwVsjvGM)Td!&_U^eFvzq z=d=|#fS+~7D6CRX)ABco)|>4wx`q^J!K+9H z@gea?gEOU&7*D46|LlLDDTF?L@U)+yYgn}=Og(TIi@7Aq@3l61I|PbTI*Ow<>E^83 z{KS~%?49=^XW{NM@YBBq`ta^`f%emp!|jf^cJ)J|Gz_ET$%FhAA@d)j9ln%XZ)!;?`+Ks2X*}>Y00s-#Bfqj@OJ=3NtOypgI5dWe~X?dS7 zx+1FwF|ZyF9uEq4>$*roD>o|8f zL>kL0JXNuTeK`C|a!z8sQ^{0zAZgGo>hfK?YknNzb`hAR@pkG2eJ>skvm?sMgB%(y zFKda!%s7BfyxZ?L1h_r(R>CK{Ws94T#xhpJ97Y`61xccJY8S0gYQ-L2A#c@*^R_N;cs&}VV` z<|z|Lw!rWx6@bG`FTP)3jxf7u>(T9`7J0L}cQT@i^sSCOgK{lXHE8>!-Kqrf3tO?| zAstuLCdld1pu3^*s#QlZ#Fx10G>vR7xlEAw+hC5KPIlaP^h9rYc|m?X^!v1ApzHgq&IW zccZYIP9)6QuG(@^OoiVa4OucAL}HFL+b|AeP>VJPT1|blw~vZgoj{~YYdrl0LZ|SY z52IEBc8?#3ILhoXx&wCVxe(y>{nz@pJFzTj5{gyKo5Uq&0mzOTJ^nV#!8;gTduE}w z)+UVAEy=YLVNC+o`#-zm7P%f6RLuasd~f%7Nu<|EUf8 zn%`kr2|^oM52T!oTYxf)1Ws(tlmZC(k&9dekmWZ_mtX0yGfgXL2K-9Fab z^co%?bz%oE;#1CjX$yE}>g|}dKqmE3WpavzKKE#)Veq`+J;8+^7CXi@+OO7x*CjWB ze$7yXR_Vi3_xh=K&*dxS04)?lV_}C`MjWvSu zWQT6<9*fHiB0x@&s`h+Z!>ugci=l$jPS`|@vPc&rv)*X$ih5+dC$MNX=N(q9Hl==% zqJLR`JaG3P5Rea91=s8|hnZt^ftGfsLYCP=g1oirF1csaMrCn^RRtYCenkG?&;0+@ zwnZoGnxCC9*#xQS5-?#&d|2m;oo94j1hG1v(C#mDeC|6W6TYV%G8e~ zy5!>Z#gGc1BC0*|KjE3VfoBlO>kg}qif`VF;jcmF_ z3f>6m|0oExR3N@j`Cq5TM=Ay~gd|D20F3(hUqT4pT!GYP&zu=+4&Q(L(IryT}FZG@ha3>dE zl>JUkA!bkkpsF^M+JM3s?zFQ`hxP{Z@77bm8c&JlgFKlDS_iT5*)LS#T-8q1CLtwQ zi#X+rP?#$dMjM}MiJV*R7JXm}2t?`bB8c^{IU8$?3L&LKy&hKA$+4qneYq5Oz$@>V$F7Ud~7Xkq#2aeO1Wm zI9&uyz-ILNvP2i17Z=d+1d<#HXBv!eN7L#6jy2{D^vxc?NjHP8qm29mSsVRSpF1neqkUR4NU7iNL0xz>%i}G*+>w1hSNObM z)G!@1+*uH%^LpytbKP(&4{6y%!MGOUfl@GCH61AnM8%pyRl9wBtJiqozW}-+1M{Ea zY)#BXR7}4Eumoix4;?Z5=sJg)=Aw7_LiP)f{6hDk$15#9Q%>>;l|CSU%NtOnc4=%P zg!5`{5PkcvL^5BdFP1sN>Exp5ewhK0at>RX|7jkiJC`18XiM{{$m@VqI zcYeh(iEvGE=q{ig;f2DVo=i1M(zofsn-Tt9?f3VcL_GS>=)4{_*bt4e;DcbZaN!mg z0Q!9*>Rnrzc&I|TGX;t*C4pYji7El=ctdE($}>C9NI(6!>SXCw1f-5_05m9ZApo8>SsV0t3@!xj?#~rm0$l7|E>FJCC-B1R(y1R^n{C2@oVPH zAAO!2P{fe-Yf?I z+StEMPoi=Li@*Mnd`o`r$?8Rs8khfkl{OgG#N8tm=-G|Wnl`kp`yWl(<@`tbQG7Qf zP1)+}x%Z)-S>>)z@nA8AMi_&25t87*xq+%h61d6c5 z81YsrD6!fYYD$t48nm!mi5?i#XH;$Wglj@%nOw$5ubi!@mF~x*gn-zuhM;(H$2>BTD4T! z(beMIeRn1H?wNMB_?9|4(uU*V6WMksN^QjZPW*w5P36DsL3CN!56#76BHft&SR_u8 z6KLHk1CU>-G&Rw`#fTVus_YZ@mC3|9O|19=-T(GC9p+kHG*jY43S9iWQD=qXm(`n3&;s` zYBR~(UZ3X^2w~v|nE}m_j6C!7x~*m3qn+M2>7dm+l5J+QkX8Rp4GVozw4H6>g>Xnu z5an(OKVV(`%;6WeB{{{q0E3#}J86w43i{(PV=8WB=ctBwat%4GfItNA@8mc;ntPaN z016yNNil;KA0}4xXD_Mec<(64-IcS|;ZD^5A{{k`A51D_0cGPBG?RW3)(lyn*bR1x ziXb6RAat>}*lmKu-P$3e?JOzngA?oxtD7;tU_Ar^!^48`!ScD^tZ|_esgW8gofhWo zT_(?`_M7kXItNTA0s)XK+-=m5M1U)LbOVnqV5v01GO%z<$ca}6vwcUY6K48Q!-R4h z#Ulu86{C}ned1r}-U1FTdsC54J=idgCIHvVd85B?q!-9FA})($Ez2R+k2Ax zY$-_|99c@f_R@rOmluz6O!hVMv*0Afy1xkzMT)d$*HH09F2Bo0B+yRq5Ze)ATGaThs0t8YT*Mdq zhm@=a58IJ5o%FZ2!iqEdUnKnMiu8}&P;NKy*8G~9ilzo|ASZG(_0tzQMPi*89xE{T zhS>Dd>ZorOQ_D5BN8AKy8qX;?UGZ^Yu()F9^;hmLMTx|yDhiw(Gzx4wsgN7_6Anm* zhqGRPkUq>*^Mf6bjA~56RqReK6Zz5;RGRN<3UIH(?4A~G|2)|}Hr^k83C*E>qA4FR zdqalJWP3J$%Wr664pPn74|$N@%(o(7e9-$j5Nz}w-8Q8io5lXQ0n4x{O>;PPRMS}S z>cSVm_VrA>GE{3bLi6d+$nWOQhBX4|c`~a=g$HcmETc5Uf1A-5@0~f2DrU45H4aE; z-YGKOsh{NyoXm6=Xu3Ye=ACRtwdHxnBJ_A7ncOpK9W#fYFHI}lvH`@riU!+CN+j!) zkibUGmv^FHY!btWf{JRgmIbTD>-g~#)mbUJ23_~l<$Lm@aqXKg32*2P3?o6>cRtk3 z#KcVfRO0fs@&OlGlhj4!e06gZq!9-Ve)FO-n2gGe6>jX7^@DN)KM>oeZ?=&@gR}RzZ=V0=DFRk3}`4m(RyjTm|%X} z%@Y_F1T`X9EQc5ACi&}59NwqNgJO;_7?)!z?nz9f2i2Rl9fSgVfkYew;2aAN_AT7J zjQm-j{c}f@s9zf1od@e^5dEYXwhdhv7O&OVY*i$>rbhcK3Gg$uhLGz@DO36bKj>uc zMM`^^)5`|1P2(2l@sOdo=(WMo&SrT`qmge0R%V@QfiY*;i)tUPB7MX+Sbf%Qn`LLX z&MosoGQA)W(2O6UR@RDCpFA`k<#2i{{Z*gzG+YH@jYU})2DhN%nfe?d>1W{?2V746 zT3-Lcb zM3kV%$qak`!VKoSrBsANd_tRctk|=h^`zE!Kicl`v#Kkp}%~b^O+9qBM|R zCaYi~w(elqGDnUdB*TufSgE zI6nH~ru3FP8qw16BO9LfLKNJi@#^_bkNL?|-9eSk#mB4X>@MQ={K+c3{v*kf1VE+wnWF6M^@`KgAtp+p5;;TS1l&mQP-aftBi~(X1ZgE=ui?f#ll#h^9gFyO2~uC)fXHP%*pFVWXj^hygR|k-(^h;u=9W_4qFRjz)%YWIo_{8gv{VZzwbwq)M_Bl@ z&@ivkC!T-zc~dF&!)`;gM|5E-XplJ?(PQgEa%x1iX7PeF9Dv$$Gk;%9*Uu0Q@e zxtgMcFTG{Pf}7{>XxDb3?(*~twt88?PG)&?u&j(OW+vy+$6t+D(d!B;y6xu!Q5``C zQO!pC_V@VICviqGLxhM(klFqn)-P7=+;vN5cid3IRCTg zP}wR{hY?t09@i(Xuelj@nqj7kxVla}hjy+BdYX>SPsGYFGqVy0ODAVP=65!6CSy`0 zhm9`phDNzlGGiPf)l_^{Sm+FiDr#5JXTv*b-S15D z3N+A(XQaW(V7aT%Mkiq~4ivoHt&{zwybodOQ@kXf{WK%G==B%ePnD}>eNtqcQ+jU| z>^@DRC!n4e=)W~}IXvmEmdFG$J`0~eNI)*Pg?V!@_j1_^f5~Ki@g2?d4i&B`H$>bK zUWd7pEdE6EJ!7me9FlpMRBKIJ zLF%?DpY($Cek~`){eUlgkLCPA!>>y~>wEX1_SlkE%$fe0R6DBsyF=5@gc6^0U^**% zaQ}rVM*8uup-Mb5MfSrNiGGpZAs8mNl@F0-97XyOH!Jt5qxQ{=7m>t@Cqjo!26b&r zvxD>k>&QQ5b5WGX`oss8>Tg@l(*16j+@;OuZNlpgSo-!;gm`D`RjS; z3%K~u=9EG%{e4;iB#;t?s?uAG=#%v5_WGXhCRakPhz{-dQO#GSEL%U3g`- zW{1jKq%rqX7j{O|0}z$CPNZ!IF_&%VaeKW=CFp;#hyUFPX8&>-FBve7gKB&(t(CRC zl)WNT3ZoA9R{2k@nK%l$`jZ1j1zpd44?1o8A27KYKktfZZM(XEu$Xk|gII#tx;GDv zZYN3ACJ`y14dtgBN^d=KHP4jkg$qq!r*0J<{KfP<*5J>s2|Is;l$cZCj!XN*+7rq# z(tJ=DJs`}LbhMrF4mvwOCACHVrWbEA8_W?D*m(Q&7Sg{8m<``|(lOkK6g}!oFzQ2K z%F)!f2)s>~#cdHpy)?%U{tVH`NDOxgI$82XFl)@l-Muc{4Z9ogo~aK%6 z!IJW0o8~c7jYuL56!-Cc@bn55J1?bj`mouM{wvU$qW!Z0$Cfs*@UJHmMa9|&dO4$%GVXoQlaHgMRyQ;qjKc{?NO`5lkph51v- z=MWSA?-ka5*C!R@OxxX(UrDAHPZdOcePqBnf*+D-G;Gf1CDYAr@$fW$w3^^Hp7^3j z#0wWeCVgU@%$HTG-%c3+-Y-5>^TP`3pDR++gOTXF5v-+IKcot6NE3L%(rdZz^%`-1 z2^*Ps`6^tUkgJ(-h7hxAl&q`Y&m0;|0fa$s zAI4l$gmS~OB7b(wNELApigz_)Ptrg+Y;{auE2n0NJ$s~K7*jRRc z>@R|F0RQ1Xmt&vfwO^R=p(C{8@t6l7Dh`m4`Hr(tjYX1I?QT-DF=H`ae;VA=blNabuh_LKc;q*% z`l>9KNQGIcr0RJREB*|8fR!scf|h%q%dw4gdD*zJP!iMHoc8wofdYM?B`Nw|2h#W1 z?6OS~P9bG1kYep+&d_)*dgQ9;t)PAQN@P<8?ktTLN;r~?J*jL=D^5)6SS;&g-TK&k z@8QNzNj~b~>y#qB))~vAQ`s6K&qoK$T#uUb1Vl}9lRc#@-Jw4TCm6$6FVVo4PtIJ? zCmGS1^pFDRtrnh*ig|y)yul@%TJnU-x-UV?K^6eae~A*CyOvS8v`X*uTA)Ah+Q~M; zQ<4q)<;t^bz_Goo4Vl>9JWb5ab;RCgo#61g92;FF@}0)ZJ)6m+s@i(@ock*WXsddMn@9i z9%4bCN!RYAlW=B@bdFr+JzO0wOsr>^O$96;ekPpxh`(3$BN-V$K2yrAf-BQt_D6ghhutfzZV!Mkka{n!GccSJ;95$OG2%sW4BG8k@JRD)GdxpANJ$DA3 zD2hzeWM+SAA3BrGsUyy1`J8ecyx=Wr2PQtDJCkU`&UyoBv`hS7 zN73jJc+ngk9o9n|wUjXxsAsYw8+M!cepTfEv=y`bS9Up!g4wlGtYz9%+tdj_wlEB@ z{Uk9TC;f!KhyJ6e?TtQh=-vUNq@i+0jR-34%_txm(G=-(ik z*P_wvy>w=u{}%V%q1WcslA@b0Nw;j<6}xjW@pmKP9d12fceg>7&Dx)9zQn@cACq*| z%2jGqrBZ0b4Y(XVdj)cA8KcXP?)`H`n}UTccda~4GQ3;F_>Ys2{-jT-!m;1M~o00P`n zv8ePbyn{KC_@Vdr$={9=2(mgv4v27nCz~z?={hYRb_N5G9cG_?`)dsQu%L4pE(Y!s#5yQYimh9(O5&Zjn=pU}MuNMc{u)rFKOrNkp9e8x zP+Pbt(x;+~5N@Z9{X82s!08~34oRsrya&?s_v)ZSk%FyzFYf_m^zdG(W-thSOL6|O z%psHlSCjp%ePhs*WY0Z8O+eq#T>s2d-R`OD*&Q~d8Q^<1KJc>sY4oNER@H&ps;yvWga#)P%9h^6= z!U{zr@_#GzR1qN+4!NVC@)VtRkN-=GBQh^Y4$@5NN3C7qF_XSw6BL*F#Yf#16~t@U zd&%rY4>z+xi*WQm1*oU+K@p|f{Al~KuU&;va^X}-+^fva`HN4cD5mfm%VpU>j~`NFU>?< zwLNrpRf}|UIGx1Cy-hkkyRGB=caA8-Uo#SR8Ack9GA)ay+8>9!9$!N`&FpAe99VMu^hm$-ih9ABwRSdI4hwgcp@zyGupRP|1@0Nt8HJXWcD6oZk>eh zDnpp}qqZ=EeOu(Y9bH2q_#zZx-!&rAC*u-MUwZRX1 z$~4ltS2KkvQV-dy-LlrI0~0r&2gT*Jn#2kZ84r{ZKel`>e2yw?;=ndHe6ApDPapg* z0r`ORFG^sx@3H~x>Ftv5wu^X-N5&r@!q+T_Gv&SN8Ncq?a8_Do3`+oW?z`$br=bC* zA!gzk%gQ%J$!p6E4xccXr2+!zeC~CAEzieZS8mhw__tnVUtf_=qy_Ash$ z57i#CfxGIUye&Eayn2Lp2W=~+7imY01e&H@e_y2x9Lj;Z9ty>Sq2#?B{^B*6S)|!~ zc(7D4t$kO|;ympnBvBW7B8P$Yj+Z)N}ky#DV{n4-MO-U6|ZCL&w!+L9$C+82EHto6!69_%FftG1%DZdns9 zTEPYAEm+xH@|lZvwoDh^i$kd$z*TA~DTpv!E+M}xCYkpHkpklQP*ce>IoL9`DyN^z zfBT(^jyPqfWK=j-_;8zlSVoObTlXdAlnqq$qa9-C2b75bK_D!_yD3lSR&zW-a>b~$ z=Sr^#_i<$U>r&qDChb5?^~t7Vnel@3u(J%{-!-JhzAj%8O58yN=vBK6rlI2?-V8_1mAN|<&+#qsxUQe>9JV39JKbc(Bt~^RLa0a3b3|p- zAdbfv=;GFQ>=R5B>Vy{h=X{F9nkWTH{WgB@O)Ndi`J`EOM8r;!V zB#3t$R9Z`58S2=+Q^S~fJ+(@sWNwnofxoZ1ZWxPr<>Jrtujl_z+P{kHob|F>EEH$@ z(6tU+!JD5qrvrx_u#hVDN@UK}5Pix5x3Yp<7bAySwucca;C$`*t3OVfNZ6`~r54%eZyQZeBGuZ@(M3jJgeCJ*A9(FUIU_gsP=2VIEORue&`In&)yU22;r1ZC|42v)(1AMRFl!Au2 zk40Taf3KMgzfXy!XW>|?pDU0Ie^p`vuIg&d5LuO;$D5dxLoUW1ne^KaZ|pjOgKZk) z_=8}HnlaM#B}UlMo$$c%Cueuj;U^tR=@V1}Z*&HmhsJl6kV_M=RB;bt`aRG0(G@oZ zRUXWfhBN-NHPA}b+ysNz=MVD-BKWCaLPD>u)LSky+*W`*Mat(DXt%zD)^gK1Em6

x%rViv8f(t+hHsz5Lo}z2`j_IC^8wd8G%x;*J{1 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 D-$O9{ diff --git a/airbyte-webapp/public/favicon.ico b/airbyte-webapp/public/favicon.ico deleted file mode 100644 index f1e01696c6d21d2f4b6bf1e98e286f3efb4fb585..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11438 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 z 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 F`X9;~S_=RG diff --git a/airbyte-webapp/public/fonts/inter/Inter-italic.var.woff2 b/airbyte-webapp/public/fonts/inter/Inter-italic.var.woff2 deleted file mode 100644 index b826d5af84b3bd70535b6bb993f443a2deb46894..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245036 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�LzqE;f#83j;-svHFcR`yUq8K)}}#m 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 C+W+PN diff --git a/airbyte-webapp/public/fonts/inter/Inter-roman.var.woff2 b/airbyte-webapp/public/fonts/inter/Inter-roman.var.woff2 deleted file mode 100644 index 6a256a068f0dce7b44f8314bdc735ef91b35e2e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227180 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�J zkTY-Ubr6lRJ9d7TsWXcygeu*AT@6-0c5u!@y9vtO?i{`7ztNx(5#_H8PAJYC!Y53=Sq7HwHP&9I8MCn zfEuq`zaPNIp~os~{L;W8#6>cir|4_j-Q@$g3%?f)s4Vm3-CeH^x8OQkU8q>QMZI&| zHKhpWl(~fjGi4ta%I!E$xJNb(MGjZ9I!R{sewPN%^g=rwhGx7gMVCw4uS>x6&C4Nm$q_~Q+JPFSzHc!!dd;u=pEc%Q`Zt>v zJ7XB3Oe&}jM68!%^T&s)IR4AlGiLW6Jp!`gOMZxAlxr3qot`(Gxb~cH=hbB~@7#Ubf4Y zvse8$`oB4^Z_&0D0u%_EH%2)zmHf}qCR{ADwfRKi=;*Bm(_dHtvY3jKxAt5Nj4QIS zR3+}qi|;j#^9zZEMMT6Rg8aNQ<9aPqY)Q8dRSnrw!cyt!VQKHFMpR#^6+R*nCy30q z)005;{|F{?b@SBAa9oKLBHcp};O zBF<~4L2J|-YJ5tOCvG=BFwWD)(D@VA z`IDOYu}Ra=%>KIs78JTPouy$51 z+EH}bwnE*TnuKYKD}CB?Cl!0;y#*}RoH=A9s3dN|R>(HZhxK_op-WFBAE$j%@lNc?c5-W;zTHn zv9v{(&h-g95LS zyWP9q>xXzE^HUH%`gZ<%w`?@oWkxzpJ1XaOR*lER-_t3A>7GuDL!%#l#4L<*Hp?~- zH-vroynM8~a}TT&(B%Kw#cQ4*22G`{Gd=WV{@b{=cS6+K9Z%lOI${<|oJ~hLCdhPI1ZygnhE*VwN zQ`UGYF!So&*UOUnNkMRr$dtIH`!zWUv-p?A{^0LuTYXe?`VB=$5BX08Unb@sV!TyO z4f+->zfq|F;lZNgt)}oTlX^my%ZBUS)3~9Y<4>uq(;pdGfq_lAfeYnP3rJwa0|=x= zlA7DMYlKQBTPT+Qs%MIRyQ<~6d9vcv>yIB#F7)2s&GO-cVr70{>zR+AG^6YYekiJ| z^y9(UP}m~9>CmVF;WnoE~ys)H_SDen&I+rSBVzf>Z?Mq&0(j zkgqL7QukO}U0idlxV34R5%R9Le$_XuH1qtksE_}121!@90!IWeBXVFyZ20B~9zcba z49n87)`@B9SgSAae!Ba9qsPnFjUF2>wRHy2583&_wD)ZO5{+>X}7PmBG`kf z@|KX@(-Tu=qj`k)#o1?8Pqo&SJ-iQp6%9P;l>UrY!Tjw{5aoye#gC`$(29d`hyLnHaW_O#<21_x5GCh``F}5g;$x; zDs9aKwcaXne1B^E73VQ+cl8MWV(z4Dm_iQIo_O#w8s=Mi1(RyGDeD_LZ~mg+cQ;<_ zJmF$lKGV$E@n=s#dLM8iLM*lkS`ZTUd^nnyHAV3n=ZHX!+)ZZ z)acE8s~2)w<|Rirtq%q49i3K)fB7@7j=gaCyrx|_s&h1O^MtG;;@{`A`pW)qDlEwK zV0-7>QuC^Nvcp%|5`*O6vCKhjC@PZolI`$^PJe@Ny?KhvC|}6cYh1#GG2O} zR#!8asVDlRlYe7uO>|e6S`2fd_^?UorP!xV-H^$;ol}VKoDSG~L$*nBbiPHHytb&I z!t$R_v+Lj#t*Tx`i~P4k))TmSbW}O2UDf&Xi*Fyaf+gaDB*t}{D)6FDIL-xidzQJ()^+U_HH;T60=RewVzqaU0fagPk!G-I|oo`QC6At|x(wW?KBg_~C z6OhqjNzpKmxUb$z#9Z^^2IQ$pv@w>O*fZq=23dIIL zz2WYvzml7g(^fYyqROMX(|p!+8snXHZSAm|@tL5?>aa`Y06aj$zqj&zrF2ZUpWb*w ze&Magli$G(&Q*}XIi6Q6C{f}mw|5VgWZq+h|JP)jq`W;>)@WL9!u36p1}|v(ljvKY zb}BhE?I4PNsL1t){U$fcF@v^$vhgN!aBLKd<~`JV+>(Vvx)y|v-97iC3d3VLn9NU3 z?i#Q2*ZB*}@LuX*=F{7lHjsg(dw=LC^teL$qyFPZ$z~J+6%wctL?$Z?w7|yMVvP`P zMA%j5{Y7qw?)v+0AXtKl?ux+fVoz`V$c;FSW`zWc%_miNCwwyX#eO#5Qhvi@d(Yf= zTIav3%}^k(6b_j1rdt&agI164hPYNEVFR^R>#9Dr3M?L$_2j1|}YIS?8BJ9uIp@zd?9DCmu@I^WU%ce8}@b zW_bag58iK>G6sFq0_d9zKHNkta44&xcFK>1n>V$&H?O&p?v;rq08ZKl_ASPQelLE-P0cK^VtzqMSN6}75Hr!e##nlbIsDNCzW@$%5E z`af8gc0U&m3TJODWD|?8dj7{tGyIvT09K{^(TQ7ZgAD{v%HhzsKua?f>WQ0SosN5A zqaz|>V*+Amqo=#gR1%f<<(g+YC2c;osrTV6Sf$`n>Rp_stmid~RO(fpmn3LwkD^c1 z>*Uq(3|d-_fBk#?x&7CkTBm;9#!(1fp8`o!dZ<*gamPzpB{|F^iYpC;0ZA{$*U zR~#8uNLT#Z8peP?;-ukhe_>Nq)@DCzc4+kAm1Onh*%;PR$8zem%S3e*J#|@FUVJk# zGWB#^aXIilPz69I$bbNpF_ggd!1=V3SwrSWZWF#qqlfG5_BY6XhtsSt=8)qG6rR}%bD~R-ov5adiVqO|MxrKbpo2Emj3!%PntNZnr zyA`?reQd4SWH-y&F*a9_lri}xyv#T+{_=Z}8vDxhms9pYEo$kV!7v8ZoF}5MRi+@C z2xR#{6(ZYnp@{eus%@}H7`lCnf_@9^<{Rh)D<`kbgZsA%Z?=X}p)>%u&B&LS=7QT~ z3{+2&Q+SpGZ>xtTo>;^iv0)zD`d@T#=+z@+B!+q6f}bN!)V0DW&;&X!0WDmh`N>tmcnMK78=uo}d8q~43n!eN?S45Rzk%E_E z3jY2;TH&r^n`3lV^+LC9I3S8YRId}A;fnLcmuob}`+{l$KqrWWvPDjnXYzcj%v-kG zb-gL0E2XZyF<5d1@!E3I{FYvn)uBx;>oQsLnfB`A__nWWAm4(5AZkMcv7}%rTi|SY z!ANyRaszY=h(2>UPk@A9H45LdNb^enx-IJ;=Vwa3(Rj2%9|!I-Y4;n0JA|GGZ&L0*E-KyRx}0Xv zNA@FsCD!fH&phsTVI6#l>}-4S;i9y={NZcizE`aYA4vDE?0nwFK#r1fQM0L}!9*=VeMa$YMHcjYeCyKdGiMa{ z+5K&|RUNN`l>j0_;#7>_oAyT3BUbb5igK{Tc~`3{gx`M%J(R>&x$ATv2b)ibvFJng zbPP1(G+A4wGx7l0{#(OW*@K2=vG8oyx$Z^C3;@sr2lSw4TS0dcd=C&ffZ%j{eL|Ay z3dDO8hrD)Lj+oLCzdTxZq!Q&;V@RJ3kIZw;DqKRKi3O|NpyELEwuvLS3*>J9n!&%jAa@_$-0JOaL|!hccrW1H_H(P_*Jxf(;i7g)Yj_#xM&4{E_ zr&;@DTXw}S-SzqE7B_#;yPTl*+bh9**MYB=4*{0b0}4i^o&j#uHL5YzbZT(nX`QvS2i3PEM{h~LwaZgUYr;O3y9S3b0;({TXm# z?1b$ES>0f&F40(b!;iK-ye`=oO+638 zh_$HoB2) z+8D1iG@LpMmG13Vr`%R0Jw1I`fhs%<(PlI2X_R|$pV(h5V34Yp0@7JCX`u|i=gyz0 zx;rDG=WLJ;$PKQFUfxg`mIkAdm@vScA{5|&KJ>Z4NpGOL>aWD+m!}QK zolomCIJ5jzyX$w7j{1`yr|)g$Ciw|j87M#} z$XBY#txzR_D_>3So(i%P;LrblcDVf4$YuW@Tki68<=yShPkUoO%9byD6!h-dbz2$M zfE)4cwi)5bD$snD8uRe;*Nd;7l>Q=@Fn0dW;ILLp z+YMg}OAl}QT4$jm6R0K3h3FfH|804B(sTIb z5xGRd$cmmPLlmpMosoR&Vw8N(dhF{{LO~7WU!5cW)m-veSzQT?@EYGGXI1mv z+d^W6CvW@5=a1q;&L_!uP1;*4dwClxZz$9ycz-vxrfcxYCsaSuEcvjnW5KdZdI2Q`^Wf>qqHtRONsi1X+zA!{rkpYmJI43vX_qk>#AHgCVj)tpl7eslilnyOb@Xe zT5ok|(p#5=b<4WfhVL|dM%{otp@(TF$ODeiUqaqFzjG&GJ#1_`*&YBnh)Dm7B{tg(G(x{@QRORngSWE5-}sMxC7*2f4QUFF$*ePDy-BrN&ClC|SrN zPon%wt354TWZE>=?f- z-QV}cX=iWga(c!Hli zmcB|4Zr^(?JnY6UykOu?c&hTn`JRC&)h4O%oI+Bm<%7cy&c_AGz$^p>D}Mpsyc!+l zE|K771i~dXyZ0*-ls)QgDg>G|6&`rJEhq>(#0XcPOF7S}uRaly*zOeGsG78*+RFZ$ zmD$j(Tu{6e)y({q;}sAg(F6}Dq-n-`#qhbMNt(ySJugkTzj&@7Kg^CW9nrYv^R=e+ zW@o|11c8v`*%)4gtC}jEF1Q%hT;m>)B<7KZxg0TyzlnQ$b#naTF?{jPA|a$(VYo`B zs8kiiSazt*IO(MpYBC$s8{tO&^Qv_}{b|c1Q-En6eCk~4U3F1tPHkh*$IqXEEOMME zLYb+B1zL}DYtb8^2X8M4u!A%Q`5r!hny)&Ff1P|DF0N1G1MeOoVlZWhR=~mKTTP_o zj5{z#5^1gn+L9P2O>|kDZ}*vce_>`+Qw&xU`8W=(poP*(^f*t=u!w<&-;K4vM|rqzhaZHn=D z-putKX!IZ}dXxR;5~)s->U%;qwbzML(N+p&bnJ{!=7%o(Ynq( zG~40)x%c}rrDP3}4OV$>aPu9b@H`O%aC{jj6;>cK1PeGtkkY!`YIEV z#Y@FR$;3k}#$&}I%$!Js#f!w2G);#kSyGOPxnPzmQ4$nP5orodq=~yh5yHWIj@3(y5Vl9qG8_>4F|@i#KV|jhv}&{iz!$bi)Nl8&e@O+Q$36v_%zH7ji);Xx%R0CL@h#*K21C6Gl?Q~Zl%Ld zMv=MlW2I;*{8#k`P@(t|!lag^K=lVuA=f_*`cM?mp0srND=(X|A(`=ZOUM4xv1=HQ z;uK^~y?PE8AxTTs?z{Xcv?cFJjTW?_AS(Z*4`7a1K9{^(au6pbQxbBrBSUS;$TrVd z1d0&se&T{YXDX-2ZweqY=Bk-vJs4U4r>`v&Fq8m?1_8ehbzplAqYR6b2&ZlQkG8S(7MSl&kowi)76@JH_PYz!W;7A6WR+e z$TE;U4%ovHNAZCtE_h9GG>E^Aby=mo(;qpSEpCudC4hSv37g6ejn9GSfN*+qc2N>Z z866jqL?s^#-QVP*aY_r1l8HC?D&Pw)rh!8sZI4q%{>KXzgLS_38qexeTCp1x*-T+e z!a5ZRRq}?m=1ov0jg|08I8cx3jl%!_UQ&3@4TlrP*#Vlab4e!8U^}GDM!hd!HPLsK z`VO<|YIiQGS3KLkG+X@7Y}{W9TGtn1*v6w^Y|hH5Off^xc&SpJk)8$C5onccJ-b3u z4`zryxUACGcjfYx^H)vv{S`LaGQ0R>3`s00(Ur=KQXDgOJ5s+rzr75kP!`=%nszBu z2V`sN=D{WNZYnfdg~c-BnpkBY23(YPnn7ez*coWVTb=4RUk^{td~<&sVOxOz^BpQH z`Zimjk#eAs_!!y|MJNHY*Qv)nwzu^7z{J_(oxcwL1$2X~*e5XU%A5bTf7j|(Y!fTk z{tPG6s(UpmMXy$-$?LBY=l27206T))WE6&BF(Dx$hlOCIhr=)^P$&%#ufP|&)x7Ba z>9X$Gd!5rO-LV?2K%m!y8piv5;O_5t4|eUnGEFN64S%0*_sCp-xcf2iS2OX17^bGL zEHn7M;A3Z>u}pG%m6d(=I9m}LAvg#{iUouiqUsOCZ6IXX) zwd~3-D#$;gviV7b&lOKDUkasZX?$fNE->$DWomGW3RF33Ws@;Y>FN+Dx;KZ{My39@ zBGU1x%=@V-ujy|&Gn9Ra)zVa9(Q!Gw(6}&_Lxl-tC;n#o{;ml%fBIgw&WlY~snOYj zeikZr!HGK94^R9O8#~Anurmqh4JtU3NpEPNGlfH}%9j|I@?-Nkw@~CZv4l)Uk9rg2 z&{mZhpFnrG(X!+F>lDcqAD*YfixZwVBKkHa?i&2;L;n9$0sps?lP1@fCB@EM-|Ig1 z`bB4&u?dV#d;;{$HkK zzpgN#9RcX#9RXsw3*OQF+zI~J{=50Z^Ib%1snfCxf6MlCZng?!k(d8oT~4(N*nK}q zY~`CHIaUYK>@?r<5tk4#SkSNxJG{1}PP)w5kG(MS5%?J?m8RaoNJZgR@<5Zq=f7X^ z0DlKZued!I8x#)oxfMPWr@Dbx;aIB2v)?g=r{A@GEBF5o!r=MxPv6P|;3fD^miH5c z!V6{p`&o`K6t-Kyg6`~Q1Ju<*$(MltscAs@`pY!wshHNv-f}sT^}dXJS^<=lLWNvY`X}g`(m07^?Y%T5O#>ySgh8+sEen#mO{Dv{%?6$$Fp#a1<5k# zwKZ+A1pfJn&e90hHdR3X#9dcJEDDwkYTBp%Rlh|#YpBuU`0`r0W<@iMLMu2(R$j@G z{fpBq`!`FovWZQjO7hP>rdPo<6&Je`hea@#r_wtsE`b@6SiA!CswHK}N&3lj#oA#| z`AUw%s9&ehFaokIOo+%ZLg>EQ+`YxoE|3jKIzv2SlW{tP^)?5c1;DKYOK-#2m*J(5 zcI)C{(4L90TEd*o1BDOM9D4>pEC75tqUK3$6i6gZ5+|08JF8D3Z#Z{pV0@*PAQIE~ zq5`&Yq2X+L7K4$a5fmlbvPrYNV}J|QpYiHg%5N+dkgds>tCb8Ts#0KmLNUxl)R^FRVsC4TY?r zq^OUO%flWvr7ygHr-kET(R{af9;pD$gqN^6|w&A1%Hd{r21tC$?ZRfmd-OC$g$G`8peQu!{ zl6Wv@ZmRzmlVEN3I?R>DCURfyw8d7ArcxNvag8i}{S&V$d#w znGWzLQXRLO#oE+6SWsvI`4k|Y{R#2^TzRr6mw$>wxAgvuW|t7ADR9N`${-2;9IegF z=P6ENyYs|nz_drkZPx@3QC+fqJgK{>PL|l3_N+Mseer739Al@nuNg2FFs(bQ2D+hp z^%u}_1SEMD7VTE--*4CY{a#fp@M(dSUr1z%FTLd&>afVRXB-lt@Qjiq(JY?z1ZZqVaX|m=j={Cqwba#(j zSls(VGSE5}hK&r+miNIuFbFZCevQG3mxPeuSuDH2$v?e8vZ6>fX3JDFV zWF}bIXDwP;PuDTo%^iQdP}@(vDo}Kd;|fjwRYU!dqO~W5tyKzw7KP5{L8Pq)5a=`i zP}Em=c>$Rrc8ZGZ=#7Dj?P1)7Z#jTU8-KlWw)m32K)gNbNOw0xvE!8vE~H;BI0wF3 z1@h|T+*d#u{+NU0Yg2wQGfS97=?T*WC;X&x5|nbu{m@`yO@>c~#WpO{4rK1y$TOwY zyXk1vrU2IpJC*6|k(ClXE1#C&uoo+VfzY1s6)XGVNT>2cds6k?+57o-R3zWIK1_e; z0rsxjYW+9UJEoT4V5;hzh(~6~VZ;J1n_ZAbxm*4In|oJ&_@)SZL|bx9l=Pxk&3hOa zL!v*gx>wLfwm_gyL1T|I6wDT;z(_|Ua#?J4F&n+0z|CsBO4UrhJV)aiv{GBhx7IgQ z3zBmi?j?dF9*)LShLkCNtGvVwot0bIz%m>Zh4fsdN?SLiE+{4xa@oRT`CNWgo-k4z z`h3_pI(m+a_KmijR~}6fkI;qP;(+7mS)~HM( z#b|hPMa?r|oGZ*6VDY-rGG#-zQVl%{1ctZZIDfl>N=YCcg}6)6}+r8k*2PbIzoCJTRORPb{| zL#;wHss-3gSOkw(5hca*fe;|YbP(1C@~QQ#=Jz=;ZOg>>qHdz|0;k+D-fmuR=}uA1P)BMwL=W76A;{^|GAgD-${TvauZ2l^hSUuZ$eOWu>?Oxgj6pP@}l+Sm)VquOj1_Sl`A>L#bzl&=y6c zJ}`2ON;2ki!htGEr%e|A=zq+vhNT` z%@H=lhZEBja@%Pc-k1WjnfC3_@n;D0P3uYcX7n4;gs;DEb7$wR(t`{iQYg(QB9h32 zU9{`&oGL}Le9)l@K9P|)CcycHAeV7j0cBVKG8It!W*_kHzj@Gr5a}w3gslRFOdEdF z#w?ArF5NP-T>DK=4Vdvx`_vde!&PoyFRwTZOJEX-6ebKtq1liGTIh@&g2IXxW+9ko zS4KrlOq-NoU3x)Py3+S-bJw}TC^R}FG#3JDTMJD5mo0LuKhE&MX=y2bap#9c@pNj< zTNgnNa+}*1r0t;aj$3XRht{UGy}~$l8DegD^WZ*zRfGgvCuFJYN#ggdKH~Fdp2sQ_ zR=!ZiC?EpX96;utMOo21zfiE*I15@|IsDHMOj$6uMvT@>EjeJe6$GR%-H^HO9W9QmbqMRd)M^T+Bvl zMVqDO_EelxPfvl)>S!d_5mviAsPC{|!s_|=^Yf+!Gc)mcpvH%pS6vvp z0x!_3>D4qfZRmk$sm^LQ9PI%feI?}$?(eKDg7BXJmeaHJSOVNU3-3e9)SJPE!h_g)0yTk~DL%K@4> zxc2|`Fdj**xa65^m}v~cxft~aU-E|ttTtQfMCG8hIq5_ddOPwZZ?%64{BiuQ`K*zU zlRJCkH$b+e6m+%P@cB?>^_45Tmxr2r;1;gZ5GgS;2e55M1kwvOCT#tCf_Uu)Bu)Yc zl$7Lqsj2Gu@sw1dIik<3r^l?XugBc%VxLRS2At)ps`(G&Mkp|EzhvH<=0}Ij%qQ*^ zI#+IvrOe-xe@}2h_8O?BgzfFjo60=CYFU$BQm@+3LzSPWJxP_|Z(zEXRavX8>g){f zsy(TUz~%dP&T~Z2X4Vqmv?rhfJpdI*g~uv@wQf7e^!qw659rIA3UG?eH;&CeU)e^i z%UkS?mw-*-JXuT01oHn-LtWTPs#)j5QDax#gYmoVS3D6bOECV81}6QvzC{lz1Z;zZ z3i6cKTr4A~!D2ylw)qlkCQ<s|yHa4<=7WB&l0W4_5uCSSK!XoallF^&TqUC?9!r@D@nPeJxu1+BFo&ohN~Ew6%HOpF5>o0 zkA!c*Emz@HS0FxmJk3F$aSslcAzoDY)ecSxR?NN))VFBrph06#d2r>*14??qf;CWz z7p@r6DFqMIDD%e>kVpkO4w+jS;?N2ts!@nobwe*5&&PKu<>hsCLDq5V@C^>+pc%cz)VEsBBEFqBZSJFr^xZXHk}^sbn+-QJ^j=gp=VEC068&?({1# zN`NAiL0OuNF6X0E3VF%uxwS9Z)7jHGk^I`NEi8*(%uy9v68-`K7mCp5JD+%r`XdB@E|~M z%U*v!5`KmCSKmNR04Ep^O&W}~@W$)$c6#38=*O9h!DpyZjfAwO1M1s}iMLb8C^4Fp z@}_KIQ8!2C<}6Ae;gX#4q3pv;97z;m4vtk;5l514h~yNQ;lgcPd(!P&3Gd^gj>d># zZx$S)VvdU8FhOCE#j^b62iy_Sh6su0s0a?vh)_yvkAxm`@DC?S5^w@4+lIeM5Jw4E zuvioW|7F3!UQF%~#EG&Y6rwHI_DV~q@CMmaSz8U$86zYDKn)&2+ybU190`AUlGCr| z9CliHKd{E$tpk|dh7@o~eGrHRD*E8O5#xgc4=@BYP>(Y|Kp;HXr@hj~P@z(@bFAg_ z9cGXhm+JI3ow_tVedE%mT~2&44eKVW3eucr_yb}{8El~-Gm^G_sD-lKzRhl@fK`kU zh9dlUYVd$n0FU6NO(zG|UD8vKmhDA=0@4uiLm~GADTaf{DcIy$?-FQwd+s@KU}|fh z0DzG2D?%i#JJoYQhSn(k$B|N|qZDIo-KG}+5Y2>9$d?Sexz-wCRHmIkIE^RjLozRB zWe*@7mF_ST@mp@ zHQm1hNy2L&g7;{r*qfhoE-M+Oq6$OxvBm80cj6E%P)bXGXX{e0#V(=@llDR=fj}{1 z(>Ds}g1!F%`A`hSP^sT{Lw05IFqV_&$Io*${T&Ar6dZ zw?mM@@T{T0*`FG2`0ZC8K(%^bhqtm+dFOCY7gWG1PA>?o zGDbghyMO(;@#@Iq16RAhC1HwQ^zenx2dd6^pXwo$OXh7BIwXvTUSX$GvoF;@I!^u( z5iv2sCkh@{W*)dE-TV1iH_Z{aDp%I#*Gzp&W_JD`m%sV8pwrN@XQE2fK7%ZFx-9J{4ALD{!|`Y4yTYee$sjrX;(}HcreXGY-asLL6 zHa?!G>7^7an-(D*2mAZKZD;eLF$v4zG^ITWyvXqfLvHZwA~UMyoDH(Ubwxf zNB56LU;U>qKC3-d_EJA{V%g!*O2t^p`5UqJTN!HZUd;}TYR<6`_cbvag?R;Pyvq&ax3>#1JAw z&n4sRRvEjl^{;(7LIHPVW^kBM(SLiGJ@iW8onmi&uXT-a{sZS|HXV&6qzPkk&wL z5LnpFaYJL<<_O#^^+Xducge_6q4q~}%!|l@Y*Hq*Z7%DR7ULZMm)Msa|2^{}pIWU} zEuCW2O^s@e;N08S1D1-hjKHNHCjD%sMveNT(#fl;DH@kmA%;RL+lMS&)i_r1`0!Qa z$EC0zI`oyg=d+Kg+!{`uJa!a&O?ze;#XWfRv1jHjRnAqXFKi6^Z8G7d+$HN-iQ@4m zx$AkLXVE~H=8*R$vli~h0X;4Udc5;qYf{nO*3QKjwY6qtjdhn_^B+!U=Zo>qX}Gl4 z_#(F4rT9N6FPZLG=vbGBTc)kUi2M<0hm)PUMB8b5@;Cdc9H{&3U}QMn`I-f*v!wbI zV_${Ct$lw6#N+SoCxjUn3Jn8BfR8^VB=&-jQeJkHw4-tFzB9^@SBJ@kBAv{T1lv%KBxjgxn>S75mY zvv6GHgiVyc>yshot78VQO6;F3>Q6Mpz5h0Kuzqm&#wVEVKfigwSJaO6dS80>&0W^D zJt)8p5N%;tdZz9wPA73DAjzg6$u57Ei$m6S?xf+=jb}UH^?cpB$&Jdp|ul4fD%AY^on=5 zQ%vu)1-WmXWCgqO_F>%^JNwqrfWZpyT;&DZ1%2f}<5z*sL8cMjR?dhCF+G|$zFRtS zgmBjua|E#eHw>Wq+@f0El3L`Qp!~_l~ zB3zA1&$RY;wXXP_t`1MGa(j4=S+nnM=@FBH<1Q!Y2U&`g!OzX2ojlJ)bLm{75r3>X z-#4PPt#7s@A)e-HYZ~zLY|ix!6!z$#t6=2`}5JbuUpKB!P=wdvka!rJsyRA;s8?4;Ourn1+W7<1xJ`(OS{o$yN; zqy)0gj+2_ty)`Jb^IeQHKeOFIm68?&O%f^c&t=6fSRJ_J8~!;x=0!yJx!9@PeD_IC zGM(O$?DIH(qJI)H{nL^R$<5(m$;}LjLqM`j!cKNbY1Wp^YQNDRLS_MTMB9ouW0&MO9P@%1m*!?wOW@i;bsScJksz@Foq!^?ff-4=GIY2WM~ zcPsY^H`{t&V}3tth8S+y<@mo#_nGkMgGK_jNhU@9%x{qCnnto_n)&zNG-n|Wr}+{I z&w}wd#ZXvU8sW|gC51wN<$^)$Dku%G=Z11Zqv|AJ`2cl6w4m=WY|GVg*p`9}AH5M` zo1V^>NZ9!la~yH#-nmR94M~OKsbp-8OZP}LP`mkU&Z0PmGZgbBCv=`$83VR1{(-CH z%Fx-j#zkCkS=LmL0=WbBzS@S0_O+l$W*_xV!c&M$*vjk^rzaWeBQ_ zyr{-r$Pat^raa8?LP!eGa)XsIh>@``r&N1sOT&>yP9jjs+c^3T%Z&N7G!!G$j{)ht zpH})w`=`cF`Qn(Vc5c6~iWfF0B-59&IfvJGC4!wzMnS+@)@<~WYfKR*w_Oe3$#+u> zxp+&oTgHg#u6UTY)Rm&E#_vM9F5~olcWaCWfld*vcP|Dg*3Rr2@%aUk5WjNv&}`hD z6HZ-`N77JBWB`<%`-Q3G?3%AGDxk^PkNe?bT6#Z?_NY!RQCTI6 z^H#l}PHHSH@ey#wN_~tU&h@NelrK})mDQ--4=QR}Sx$=?9IE4DYYiM5mHAEnzIO8Q zJ^QCq*#60Wwi^E{?t3%0)bLPQz%J|IeSM$JVpcC#NXc)M-k_ z<7{fi^mGO_dnzM+Whx**Ba_QCat6CVE|V9?0EEVu<`k2SuvSePuWAD{cKx{)mO>&? z-p1U5B$wxD&js%x~7HyMY-L4$f#@FwHAVR@VP7uX3}lx`N2Mbasv+q6FQ! zk?5Re95EkJ8W92g>@q@avOW2H{{Bav@~e87#(};*<4RQ5diCn^rSP(4~qpZ08LkQK)}JEzbQ9Ns-^gXR6N%{WH}w zZsa=kNC=YP+$oDk-HZ;cXInL|z7D$)NB6&B5tVNhi7Kj>2m)MPknnqCU4`U~-S7l%w+cl;fb*`JzRHU9ky zm$#asoTj1!POyurv#*{!6q8VEbJ^)D+f9poG{%H-LT9$6&7tEtS&>uBJTv-Fea~iA zqQjjhfFJ_|;5=BajEli8VS_!FunNxI77u0#6U==HD3W1{8RaWa9aN;^YEFGAxfZf5 z>HF&ePFo$7jZSk(UiEmvO8H zW9`nR%)JW^En80bi+9GkxHfFvCUEvYP#ma^?h&OKKiZVAlNg(=jRKi}uxr{`E}tp( zCCJ~~Ygn|QI*mkS)hy0iwOxnXd(3`pM(bIolx;Axj9ms>i3uSgd%bYBr@6n-*_D$U zuOsA&FzpFonDlp*<>GbdTn5G%DYhhn4aJ3X8EA{hNKNPdlXa>}%C$lZAuO=cpk{li z@zWBYG0IqpkNhkt?N(u2UuLc=Yfx`JsHkbLb6KQNN|5i{SxW64=nl}MkxI*_`7!Qn zRs4@~>bjqfE9N5e#7u?Tcrdjne5@k=T&AseX8Q_v1#&nn#P^C^QW{s2l@(D@WG=EO zd~<>NvVoobMv_>V`^Wj5yBU|~R{~eSiblvf?{k^*w(zkcYVg+a3zrmuOXe#-hpwZR z$N!kE;*Ncq-(d*$Q3_tNvZ&nF7<7v6jojpbW_#`umXh;eu{92)pyZ>4@*-+n{03+))XuImI)C~|av}Ue z;)4hNW-^3Sa3O-jjoeat9uX zLNH3~O(PVEx1Oc>0fS6W8NIS;1TTSfHy@eY{^_hkdR*yIMM}p4R6qsJbz8KK^2>`|w{1x!s@p-rHYqyOOB7PI)w|o?PqvU@(Tw{ zX$SvDeJ;wZTAXQo$#PKnd;8N%BweeuG^H=w$o343&SGU)W@8~fX`+xh`v_KHd~|o) z=x_gwFVC0=wd2L|o`lkhXXCTpLII}%2AFDfUN+j3o$V~{TGdudq-|XJzX_DuUpdt)1n!na%j5Q-#bkuI-9E8_&49g=v|8 zKPVr}{P726$JKa`yL-;Q#*LPRw99335 zakiw*{d`jk%Vjacv(io8R#(>0BG9N)R&6a)QDyf1u|rgLR^&NW;bZu4s!Oxz#ycqR z+jdm)w$ZU-Gk`3vM#?YvP`YhVu*gg+WX*1&4ovp)iFS?Oe1o{ zD+|B$JS_G1+sB{Zcio|6->J^d(h93VJvTBE2G#GYb{O18hJ&F`SP3V@;_l?Mg`gos zBA_9q=^H=KbU#10*-`w~Jx*B@lL}b#{Yr(gG zSOxV?C!Ryid+@(gr#R}^#!1o1H5A0K?{$Qhl81j`vY)b9fx%dTE0 zWoJ!juqHzZPRA}CJ;5SUh%5w*NNc7`pyAz?Z@_Gb`P$kb#^!3z^*#Q_X>i$fV}biA zA;FZ;JI+O%1h*;il1xxDP$+TpCAaPgb70U+}^rh$09DdBs*R( zEAjI?z3LVC?sfa+zO=uLj=I42o>q2d^?w{Im5nm>C8>C1vi7( zDS1auk)xtuivfv2xKn<66WjAm8I@w_YHh+X=Yfb36W)_m>W(K`)Z zTGywo`kRl6?3V{ln@%<(s7Dzm9|z)Q1k!IMCL!>zD^jSw^kc;81H!BJ^z)LzTzcL; zk|TX6b6MR>v-e4qCw< zt*9lG;Se9q2Xhw@wSXFOgx>XpX;35-2sH?3K)*tdK=8*8(Z;}br+oH=#~#z zC?Fe-Gws@h99a?JRCE8^N||fCst-Y@ZM9fQ8=g8dr&pEoa+*{y{Znm8@c6o}MrqHW zUTw{$2SSwa-n|!16}QGF1WY0|)IT$;8dH_?bqd}!bg??7=BNe6gDdFA1gG}I$WAN& z+TWht*rbgM_B)tDw);nDA=L0iSEhy1pnFg@8xV2$2JG>tkN*OW3e36nvK>;nYu2TC@!1s18JZ2No5JV_n9cA~41}fE zBivbGq%deu4EEQ4d5U?iU{BwZ_9Vm!_;^*?O^j5i)Hn zz>J`Q84)2?$YL{EYvkRAp5=Kqq(TCECCWp`16`kV)+kwVWP`>|4>4M z=Cb5Ziq|Ib0_)bes6mpdZu|%>uc@Lri&oQEos@H0!BShsmVrUW;d*hix+I9;}y`j8CopOkL|AvXd-Z`Pf{?F|fMRGzq||NnlYd&Ajz&%dX2 zbgyPtNz2hm4Q;gr^n&w|9cSwdF)_A}yB{B!RWVvHs;G9~YWbVcSqRJe@vWKUdn=gD zz}a2a-wm>LRiSbsbS5Gb+GDPTHs-h^ryVv%o{QE=sS@Xl6&E2&0noEppl8+S@)ugB z*FLVsKh2-=Y;uz2Tz}}A(Ki?ua(81M=5*}8jD82h^^ik%(sfb2A<}B~KL7s5TI`6j1;J^bXe=FfbEmA>kf@yD!pR9SgEGYPQ zalM}HtIvCr$`l{up&xdJ31ME`g3Q)+q-~a#UO>w|N5^@nDE2KSVzuO6`Rwm6?|nBL z{iM6Gy`bEoLgf)*4M)vMjItx0saZs5%?)W1*AfNyNavX!$mjTx%v>#7T{1Q<468kcMK7pPTPOJ~8`lkacRvH!xmHNb3 zu~PrD38hC$pKLQ8@5-nwq-7UVvEoYAe-jyV9U{?!U&tNXF~5+d1yM)Y+`oy}RmD_n zb}_AxN}t>XIgWnpOaHuat;f^jzxYQ0{psTw#G2)70efKLbzNWS>H{X;3++dxRVeUsI(h+KXt(cfEpz;k zAv|X^ak{k9Ke4U5ORYpxrM_x~Q`RFjI~5XzV>4Qh0#f@|Ur5*-5TqS>z*JpxtzE%n zr~8SRFH6^ixDNYz>QK$i?CIK4mY}^o2rYI5Ei6dj=3MQ}d+3l&MhwSBZ1-S+3VT>H zVvii9Md8q>S^@5=EuD;cus(r&`I_aPorM}$)f?Yy6sq@;$PJQQ1w5t9t8ueFrq6R2_ONA=@riwcGhs4X6&}uoQ|_ zqJX$8;&@gBz8UW5<_x?G&PWr7p-^E#I3mLMAlgz;2)BB*qr5uueEi}#K5<(~88)RF zZ=(C!>C@Y(1Vl1NFQA|J@{RZq<&!~6XhZw@CsS6TWRxQGN8dCHDJ$?>-b zB}XC!MwvDfNXiO?Jy`l+kHjIt3Y^Tu zzx$v>4h8RmK;yu4rr{rO8!SF=*8820s^F-pESZ1m;Fb5(Yx76V=FiI>UU@GZYG!#D z!=i2;R`e%oFASGx$A`6=^Zg~Iqy6=2A72b6C`JxgTk-} zgU(qC&KRqWL$wu0d?EUG{W-Qc2ZFL2OO5sSzYc|}@!odZNotNjRb42NjjMY=DiM`^ zJla5}o1Qz`#Y`FQf7a`OQg%SFSRR9tsMWYh(iB`gJ@k1f$F7C|91qJrP5#t=e^-3? z!FYdPY*-i;a2&tq?xRlBg}aaI8*V@8M4h|6a+ArW>tyzFx}M9W>*aP?bRA$A5q-a!u>Vt;rE~OcI)#r~n+tFY3<3jikGEj{G!L(QmTK9tp%IVxtmbe8q4# zgs(UO8U@40)Q(tXOm~802H^4F-LD;vpZ$ISb#CZcLqsVB*|}MozFCUwETzOY<9SJr z3B9)D3_6}dH^^can?5f`&85{f2Jb0f>P)NcICpLG8s$g|E+tU~x|Kn<$xpPpA`dfT zfs0Xac%eIIij|;m-Rmb0IYBxiA4NraT>YOL0?4^SY&+F^&Kk#vz zHqoac+ijPERh|T?etN+>f%Z4@<&VsFdv!E+-yo|@rhA+737Jp%k|{3uQt(CmC38Ln znkb4CBUQ|y0RjdP;GBU%3{Bzq$JkBJ^*4E}-S+zjVvn04pu$Gi^on%F7KJu^^UIJ- zj}9LLx$VTsLWDhf5|P9O+-w3PeK}U6l-?Yds}vxB0s@EJ7#j2OUqp1e_9(&M`J>@D z-+x`DP(zjXDJIq zU1ozRmthl0seMNXdy;L%;*HkZWrnz-M8|7{*Zb=Ax7Tg$vAL!5vsym`q3=jiA?zd; z%H6h!pAwN{!;yEd;C!!b7Lq$0JNmWNh;jZns%f3r;H;d=$}^M1cu*CiSr%XJ2PUhl%t^zGDoKVC=X)?WdA0B z?^h0}3V;+jB9Boku|I)!(R1(5zds-7e&3W4X_mc?i+bC3|LcE!WBjLQ_{#V$Sl9jk z6TTU0bbYhsc4OQxtDUE=2LLk@My3~!NkcPX6`=x{vO=zxlx()=N=7*uU zG4!Qju%W{7>N1CCKg*rr%{a`rY?(vby<4mINNzVB~R{9U74neaO=} zLp*+dIDnHk?|WkGQR>^b|qga)&hr6tS8l>1WotJK-7EMnHS z((nI$qt*%m5R^`G#3h=w;@^vRFZ;$%Iv-%&8xZ(7Wm#5>!nyYk1jI6 zx{sOb&G$lc6Uku#qX|x9wl?2TxBamv`A@3t|7>--J>AMlR1TRw3ibI9)#kHZ;2zcf zy+`~fs@q>S)2=&*a6MXpLFS9boWh{{te*<+K4A=4$gs$bF>m494jz(*7cRsl!Yl!A zQ!Z4gwl7?K0v2bAt=p>>AV2OBGOT}i0MNcDm?@gCM8=i|zJM(m9&V>rywJU{aBX+K z@uBMrEHB}=Ork2CEc_nx8)#Ii4BJz@l)nK0EfX#}M7=_iZy}#6hDs)(tB7vEBz4HI zl8#W73wkT`@fmTg;W#$XykGnVf@c^tdILV4NP?-}*qd&kRzYup_j9q`a@}1L-_3$s zpr7_Fdf3UmAYVwnR>2^r?)46*1tbQ9_{W9+Ub~kUt{2m3gpx2tSQIS#K&+=W8dOLl zzBhOIhZ18qYT(KvxJ&|DaZDwUh<&nm_xt*H`bR8=D+RSWKDQuWD9p}vNpM1K0@k)+ zS|>cUCRZXnb&e%G`)ZZXI%~dOI>}@?g*8)mjd9gCMvVD2Ty~a>A>byn{ol45N)K~g zf#A|~RM#9cCRfJd3TPux3=9grHWo8oJ$$T!ZH&dnbO)3=ldxKlZ+n)1gpnAZ(+^`H zHYZXW_eNjfj;R*-z7NkX^>XWlWEp#&_2A&j76PSCBbBJ!WT|pCjPG}_Y7KD{JNpy% zh0`gV5v6@T=lp42CW~?M!P+XPUf#9&XiDo!jA4l`s%7~|Ie8uEKm;P6qT0+0iP+Fd0y)oFl(qYVfRj_~1jW`ZFf??!+RtAI#_=Kc5hoRm#3Q_e? zOy2J5>ui(S^=H-iQZ{CIOP=3U7Bg7NjIQUhSi1}fX)HFEedw{5(F`Di6ZbutW{xzk zOxO1fH$$YRH}MA#5fPZskm=sZa9Kl7se&k0q`6QW9CMdP z8jd0J(&UGOcu>?%-sLWvY3EJc9jHjS4-gfem%u&ApR+Si-l5M<<}GKnXB{koU4Ca@Y)G0@n$xgICOo4mshF-64A&wf@R7s5{y1OMwpy=K zX%fZt+>*@Jcv4=>@Wxn0Pz2%yERd9wsEXc7x%1bD9BO`gwZR{K6ah;8YAq%$4y*4j zr&qp{GodYz7Rcqq&EpF_nv=I)x8VzU@S)Apz%9E_1BKK>_1u&qr!?DZE&z9kRSQHtX?3_Te| z4GevMkx8SX&B2kXr(rYb+sM6+I35!;VmPX2yhqb^{d6Dpcqmt%^6?lW5pvlKnm|Cq zGNS`3rfW2%Uzb%w)1kx!6d{I36*8eChFi7^ov6@*D7&WZIT%)gBosDlUQ> z0ON2D)p1qg22nEMBpcXt)N&s<{4;H-I9;jOF>uK4wGFSdgAhj%fGOkSoe(rGEJU~4 z$K#|2-T_JxA$%@0dV8E2^NL^;J|fWF;EJ~+E}e8YdYmW!Ss!1=bg6abU3?AoWlZop z-efV4Z=*(UKU%a%PT9+*aV!6fpTPYYR%iX>c5x~?&RBiAO5wcaJ!t$ z>@*K#pd3lTcSQvxS8dH|OK5b>RX+ZseAUoNx%}<(Y~(8Mw?j(#$BKsmPRTV_1<}A= z?&)6;62^ZO<9+<&!#tfox^>XVp9Mjex!f}oQ;r12P!$$Z@WxdkVaF_HD>yv8_DBT) zlsi7hKA=Jma>t%ER^j(oY6DUq@qX&f8l{=sLA`hEXEU`1Kl1rw?bHtQk;LoG|GN|r zJ2>DE|D5|x3%DYkvL;d$RWXS&hshB^@&qydFlpDvQIjQdiSQjmh*CLpH|E0!=A*7W z9)M59cd3KLHb8c^!!e~0yso`s?JYC@16XD-CJ`FQ+1k-jSF1f5!*OF6b;)80s{B~9 zj~=L>S7l~4 z0JGK?oVY-9CUX3|#TlwZ$dWmf=V2cuz26nSN^<0Jxr!3-&|=)iH(VvsxoiH3#I-qwA=(w|jWS~LyadIX{&SWIEm2A!^W8lNwI4fWQ0n{P8kKWvk|J*PN9*Z|6IG$Wz+KR)JX<3ucbp4d29hymxXh|y13nD zgDt0McEK~F6sJis6{FloS* z)>^sOZ(T$!XhQ*tP)6Jsc_NzK3s4a%M8)VqjGPE4W2UX#^b2Ut@{!(|6lai8%fX)9 zu{VTW+n8W05K?@Z8>GU=!G} z4v9V;tBq7&Sz1dTB!6<)j|?~D%t=C=kR230SPt1aV-0y>ks$}3u2u>>Fjocy5U7>5 zJ98NDSPmV9s>E2hi-uC0vvgYQM!N=nRt8}%Z_h8Dus-UyrQ8s3!lRJtG>kA`$-10#aP68Obx`JzePizxU=oLQ@mV5 zW8`S$vc$i!;X9CDj8hJbqjPPGkh{a@vM|mr&rV?LHdx}xiD;sGt)A{&>_%kpiEX@C zGWWq~I*aot)9*oY5_RVUb@PtfG>>Pqy--Dqgr@+${6ath`bE5jT<#HPGlzVO{~F6H z;}1{8Zn#6=@L#%7Q6FwsexRi>D!FL>V(f7Sf=xNDAKk!rW-NKap(g`&7zw(P&M6xX zsonkTut{Itn<`ez_vNKeKR9$XZLGnv#%H9tw|so-&f*IV)93Pbyg0aNs9?UPq4TRj z?sS3Ck^fd#p(c9=jQv+K*SS!IQ;kr-c@_-@kAFUcAa~YV+zKb3vi*b6Uq%iaFai|{ zOQfOK5l!y90bcz_;k|~zbnn|+Mpz|E-h{ij^3w43auJ0nu9eOsFSJ7{D-N}| zU%fcgO%@yszS{excVHZHeS8fs!?E}wvqrP}_+f)yRbPp!uffImVdHvZTNk=iz2KuL zq(pF*(tBt+jQ}+|*hd=)X^|@m^|csolmiq*rB9qKW=sIv&k=33PZ4<>c5fy^k$h;8 zomo{?mub65R{TAJiiM9u@BL2DcCik!GY^3o;W26j;HU>R0)*Z|P3rX&`Yn^3eGJxC zZ>-cyqQ)QpV;dTZ?H5RkMgCj9 z7Ar&li%LV~ug&gN2QQQ0n}yxoFtvF`Zk{RAI;5@-}4NIRrPg*giYX`9r(SslWm^XWr5d`^o3<4oEHyBrkq z?h&x-prhx*$1-F>HXQCW^La7__XqFS-v!HCo}zVTyY^U({GoJlf#0C_c{9J^!Uq_) z?(Q-_H+&>$EE&mcxAVV{`N5^&`+*PqhRut5qYW_&KcojbI`-(yqOcDI%i?=~XC>ht zFY+Utei`Od?t5fi-11u>nhC-z;)6(|!@FtgoNgCqZ@|Q(0Tb_Hw6I2+#CGp2os7^c zsvi!+&3J8gx7z1V*1wS_v1bJx{Epnd_pI89aBHNP5+}ZGXsvB<_JP5Rly0Blx}Zyh z8Bd;8&GoHgNffjtBLV$LAv$O%s`R0K0* zFPgj$l|%hFQv5D}-Q@QtlRS2Pt5yvU;UoUE{b!{IhLR{v-lH5s#vHUR3JwO0JZBzj zPe}n-(Um1K*1Xo7`HCmcvd@;+c)at|CGnaCUn+GywnLDEiOUK2re;>abBGxxRo`g1 zC#ilw>mzYV(eZJ@wNoMCT9Apja#^{)*(aWSk&WH30Mre1BcIL&6%bEZglC<$NF-7?FC=DxRX2alczZmXHh0|iApIr)vPjmPL9c6a zo+H)Kv8rxtCEX1QfN4X9T97d z9M|mV-_O#vyKC*F{u2(^#L{ zQu^Uc)v1oPXH;N$IBNZKonWhLYEt!c-bUREez?QLW;6YywxR{!sspWS8r6E2qO{ty z!A9Vhbe;+>@vJ=*dZ^cxXHeg;8R5+ z5v*3aagW&xhu!_G^DfT@)c@vUM`Qan^{L(WOSuYJrMh!$6r1DKop;ptrS$Z&L!21r zpw2}Tq5e2)GlOMEv}xz5@{|nsTM?RbrMgO4FpH9|sC|w_D|>wn@u)L_nw5jE2*nSS zhOYY0IlsJax%ov&!w*Yj-X?Zxa>pBIhR@#}rF8Pm*wAsvsc z7mawkIe1;ex;l`}ZU>*|vfBqcTiNqRM~#pUY_EndkHUWO6QM#9{dM&e$c$#8hY z@{t6K_5@qa@OEzse1~ptYpp{ZAk{Mq9H>omD7}5RMWSC^mNq-v=iLzPR1xisG}|Hu zmf`l{VCy)fD0sp76XKmUa2X)R|1$DXgogZHU?sCUw(kxMXAW%|!R@WN@qdgdH#dWP z0wqNdmL4sJR9qN^5a~hMb)+S(9rT!Ej!Fs|QF(K5QdAw}J6Bb33z@EAPq~h@JS#uu zmQ2%XW>DTK>IGVNf3`I`{;qryM+wP4!`S9ugqN51edUXCayH@CdAD=lgVY~5(+@@9 zC?TS@%>=DM2*_(ecg1#>lQ->NU6k($`MZUy0uMD^5}_#-LFI4abkzI9mX5IIic{U4d1`_%%t~p|gNThoaxZzLyAtvH~q; zMpcT#?T=4N(vN>#2OgdSGy5h?8hNYc81X<_HA1Dessg_^1Ex|m+?N2kbPAwgm~Vtf zPA`lU^EO*bdMlP2dR-I7!9XY!6(_w!P#p!snj`N#NrMzAl~%gP99)JV8=|tQ$+PUo zitjf`4)m%_W@E0cv%27t$M(()CzxA@)qx!y#7Ejjuo)zr6JzF~7&Cq%M}DptTU2!I z@$|Jz;_&-h9dA5#o<8B#hkM$;7Jrxfq!bMN zOnd&P^ssv=kDTMzX+lC(DT!2CiylUI)Io}h%Q}!5>XE$|#pnu@28byJO>YI$vi)WX zJ-1cj(Eyg}i5zAX$PJV*kFsY8&?_o%Kb$8JB_Fp2Z;K?_{`-I6V`v=Ucd)peLgj%k zo55djqv`n%53*37X}aV)G{AG2$Hm3sO=VJ((&N_rY~b!j-jsaWdM2&R0cTol5}2r( z1tv~R1Cti!fiuSbmg1FbhF0WTbx67yK+VM$gwd%|c);u-1DR#sKK7V|{CrqK02 zP8&T6Op~>jZt7exKkS{S86zsFSCtKYo)zCyoM*?Kj(-rw12Etwp71^}yJBDG0`x~b zEnY9F6uZq387IgXf{3ANpiqMWBg{#aV^biiO7xjRIcP9;Uth&UuD1*>G<9GXQ(OS1AR71=>WSz#n+CBJl{W$eSm9>wsi zDtny>mg4XT;H7rl1ix=#AW<1br9;qxWsErkW`r9x@$+CvhptS-Kv8k=;FJRlWQV9) za+TKe3d{y`s-V6sPb+;gps1AWi{yOW3-&?k=dbXo;&#|njgco`ApR1AQBI;pdYDZGe zt29YQbH(mU)#9G)tn1iZIa${fdBP0^J~Lq&9$PUUSd%{H_G2X>V54%Y3vqT3yQH5it}k`kRBMj3hl9aC9@ zJj;Hn7%tDqUC>H|(4&|NgNT>GZh+M2sDwa|NeQG5{Df&He*+Q(43(7c$`RYE7uN?#zkT)1GWQ^R_G^ z>S2SU`FWx+stxnZ9C1FauWnv_bz>*2RulyD`IG*H&N_H&R?3;H0f|vmt<);6+j|Vs zv7$LWc_Ys(ETQZ1{_*j<2znrF_G*BS1rEwmG~s%+ghEjX;Z#xtl~zsFGV4HVu(t-Z z007!JShw%U&U1&(P4c$KXLcn?2IR5zkf99MFmgVS%aSIsbc zfSNyK4|7j~2+kPBC?HCC_Y*zEBH%xP{Ijnx_kH1IZ;q0$JHGOR!lvVQS1y-BMQ*^ZnllRJBM2~s{tYer4Klc;QByoPei zJ@E|dOdC#EE7Cxp^ zW#>P%%Mqj1f+Zu{Fl2ryr8Ni4b6pOpTxqEaqwZj<2`bJ`B}i0S+7a+usV1ouc)~Y7 z&03<~2+rZJ>MxoANAs3#^#r_+2hE1BU5&38C6dd(LAUoSa~;4Q**U zl$cn3X1u{3F$x+uOzcLf<{uPlx~nY)EyDbaxUqi`|m%N>cA+Hc(xY<;tT zbxv?FASy)-hZa-v-%28n2Eeg~;L-H{yJPo{%`jE-H;*DvX`lz%iXMHXwPQB}+s|&* zDDHP_-`^)eb%?Or^;l>16xQ5l`X~w&{hLYp=2K-}JL^#uydHEF$5F{zNQ&+prY7{( zK|+fS_BJzpN=w(K4lP|1{72-3gLW6_=hh!7MEVV0=qFhhNba=by5%R@w1}pT>dE2Y z0Pb;x^x{>1{(zB<;65U{O^8;iSz4;XRpYk>Ul7u(XYS|l*9%#D``f;VG1+J|fU*qp z8VtTfmdIT&zKzo{dlSxyP#nW>{ImF4NLV2dod+Fu0}wxo36Wsy785eTYndq4GJ#=$ zruNRa)Q^{mD(|RtST4arj(-fGLs0Au2QjM3NIVC?@jd=AhCy%~A# zcxc1}a=UjnYl!SoRf0?<$%|C35d%7alxM2hVv{`|==TA*o)8^6N5{=(C~aCgBUMJ! zLx~(l1)&QsFo*M!ifLWdlZ|ZL7;{cgS_9CzRuIxJY5;m@D+udZ&bqXnRcWK^(qeV# zj?|^;-I5`Sbto|%eb>UOfYZs#BqvIoTnMKFZ2i-2kx+B#f4oTM1UlgLDyyGF6bPMb z>geijofscw7+^MB#Lm2s=mzL`s0k(OY=MQbt!ZiN#&g% zt}$NI)cyfyauk)|ppqPml$t85Tq7!UZVn$FIY zN=T<_Wvt>-s&wE~nB%2XO-9@M&;lJX{A^G1?S9WOao22i_qi|kR5y<{Es3G3rC+1{ zVh;1kkN0I8Vhk<7Z-0zpQ%0MTdreOt%oyFsjD*~_AN;goCU`~CDsP? zX2cD6ywRCa^=;@U1ovlz-()_+!hxc<~CD52wcc2Mriv>VEO+OV!4Qq~K6x*V!~ zCiXo(R|wo`#29*)&X^*abcy zE^GsprTtW`!9b>6`1N&)D>?@mjAmDvk%qg$53Vl`U6^p)o{5R5#alF0nDrM*-^-P6{lO_R__Yh$RurS}dGcE@IKdB8s8l8d;x= zS1cdDqX`79#GoMrZN;ED1T99O(U{mSOB8}#=ZVB<5Ln8LS_US(+KT#PO2eOX@# z09ulGkK|>3B1)X~LO30$8~?Q1MbzBd|}rZuA0&|2Yif(MKV zvPBxCX-5VY*4Qr{zNnfkOhr){cz{HEM0HB91|*wytKqbBl>^B%5Jjb00I7NaoUxN9 z2GD~>kk}9s8$-}w3>uAz4I{Dfn79JbTMI226aErVdQ`R#=D&58j-2GS{?O?>BV@{m zegJa0T;-vD-}+&MeN1K}u?qT?R`TvUQg5q9s5dVrw2&XpPI>uWk07%~{@fRBgydP^SS}rM1ggIjB=lSfHoAkf{t;`3UfscH6i@=-P43VF1tDX`a41 zefUx5y)P}SK8U-%Wm0y-`gZ10^R{1}G+9)@w;PWMzM8xr(&shoE`8&Vyro z)nk0oYj|f$(1e>}G;gc$pe(v=p;0@8Eak!06kje&$R+Wy_V_}DtsEl3li}hST~s{P z>!IgeQdsj(u8Qq-^VVy@EaEq3;Y5qpAhBhOCzUC-%+@5sESaF?B9?BlDA9$qA%oyf zi2P?k5(`2(6Vet*^2!%qSP$(1%g~DQ1g#)+R7FiGqg+ifFC=?2X zLZMJ76bgkxp-?D1qeTSZ^;Fo3vX>AqXvo7#w5eRvII2ryzjZcyw-3^x7Z$52e{bAX zegv!@yg2hh6eukjsVTQnw=jF$+_ zL$9pa`HxFdXm;}`k0mg9r%n`|Uk}%9zg2M67o(1!J#i%}fj6(`CWeg9H?viuZ=pGKkp+C$2q2H#QFpj*ZYoe_i4zw%x;g88b!;(J$AKy z%l0-o_&RM#c7GPt_Ke>i|IvPE>*pY7jd^n4+uMU?-O9xL<3g?nQC>su!av;wxIeue zBHDf@)EZ;QTsdZ18fpe_`%Nje_HV68tIP!6WeC4}ojd!^W@mfX7P$M9zEqJn7*V;3 z2+q289d75^3j1308TO92&l;6WKW&W#GlVmB=}56ZpzYLoB>oT3#Yn!q=*+!xiM0WK zZq#~@_H9rw&1i#0`vr6$8gKNDg<(!?gJ0N1bof$XUFKnNXa66!@xi>{`NR2n-qZna z6?4vRKbf9!#o=4%F;IYU@ET4Q>i*S69m91*A zR$=dVFiU8m)%c2aCsyc~#X$&s=SG~F9EAOF-p)GFAwf^sa<(ux&@#;}MzU*xZww7a zHVCtm3F5fc=}E12n~XEY6R;w&f=?Eo(MvGI}ky6FN= zTs75sLF3;@aVEdVT5W#Y>H&*Ko!V!+@yhB+xla$Rwx=@q&;U*&X@SblUNb_Npt@!S z$~D!s?8p59x_1SQE~GX}x%IeIx^~5DEhE2PU0!IvTZaQmTL$5Mi+N$6kCw|^ABw9^y?^CQwT74RX2831eWneid{G)!;;wFj#oIjty_=PI8aFduRLSGQ?>gnTf5hb$+n9Pj zVv;v5m1#>c?v4`iN4{m(qgX_mae{e8PZd8fYRzu5M86_V-Jin3dg1=rH;N<6f_ZMQ zd?{F3hat5~{f~1Rt|(bdR^-G($wt0@zRog?y&*`3lg zX5m8eb?_BZXB&0n(=hD~P~Au9i1T*-X4f;)K1AG4J^NGI2gnCqPs-SC*arI}xAihq`NpZDsI+x2IF z{N}^=+=KR=YQc_n*5+hW5?W(U!k!I*To!^zVQA zi=W*9Pjm!WPMK4C_tuuLD&Wc8oAv+kAO9Bc{DcsNKS#ZHC4TPFDol6B2RT3e-mSi~ z((>Y~7ceY)v;+w2Ui&}aHu7=)2z(>h{r0xu#xC)ZihH#QN%*Q%hJVla@V^kG2Y#K8 zxcSc%eSIPNH)8Z<{-1>d1v0l~%MSN5b$7qA4vBWIc>qfTf!y`HfrNY6YzU<5Ocxk1 z1Y1L(NT1vc5pd_exhxegd2$5;B*YZSY*Cf54jd8kdGZ;*{-8 zXhzbSK@Fe{ULkW?^75K?ajf)RfdRh}_I1hZeH#EZ} zn`~_?O^KYDV+C?w?*KBAHK^5mhzzY~CyL1mz+#!1o2lehNK>NKfS~Vs_HtYUx%H~l z*{Mc(<92k=6O*002;_`+XbF@D5uXNN_04qY7&%0@B2E%)^|k=#zGzh()4c+M?=)se z4`Ep@vB2ce>_~|j^xBqgmfl!WlRD=No!|?N!4+V^J7{im=fm4DT(!{%ICSX z`thmuf=qYsqGBk@OLwD$Q9t`e8OZ?o?n}juW1$Xx&K*OFBs+s$K>8x-H0_$o{;D1j z&C#Q?BY&Z_bb@|Yr!ttAOdFky5O4jH5{j1jZV=o%pYT5GmdS0!Htqo;!*Z@}-;yOdjQBiCI&^ zosdLZxJ|&;iHt7WB*Ae@SM04Jf-Ft~a{(~wW>9Ye(AuWMBUsjkXGf%C>=7rSPVIZm zO`^}-#cd~XTeS>M*d%em^3qpxoYC+~$v0jJO75aLa?R!ldXn6k)h&XBKIm(h20P-V z%2huhj+q2Fbo9f-#aLrKsUeJ*!+6W=YO?EaFv`rj z8ty{L3||OvC>!aBVn^7!hjvIRWUso11hWVw$;+>pv@sHOnaL1oKuoR|c=X&FF%K4yEaHqITtKG6 zzb@u0h!>NxWOl@uJ26~}lmsp}h)48~><^9Jill^1^J<4-$KK2Z@Fh!6I>V3Gq-|P5 zuZD1m8R>vxuG=DZyp8D*gq5K5E}BsnrYd)byI_%~M9z%C5X7S1fjICi--(40YUMy; z(rQiQD{DUVfE%Oa_^>E~MVhODLzY}&A&QZBf*oqE%W$WNd}jzicLOfQ3Titd55aLU zeXx5hN3_r>SQ@QJEYbTx5C}OVd3|3eIgQTOF~`;dy=9Of&{>NMN&GhOiw>_~sldpT zOt_Ae4KYStMh+wuw2at?A#T?}Qkwv`q-|R~HDCt%+Mw;yzjiSlYf_`i*t+U+)zN6hbXrq2vH~r1F#x@zcn0!z-p~QX13OO&$sY;bU)O(2Y*Pd zDc0SxyWpLf*bB)=I@h~AzNr$4TACPskq&}f^lnoN4WQ!vZwjbbQtHMwo3ZE@drBO< z65=5mb68V*6S3x!sxI&uHD}`CATwKbOp8&_zmM~~Zu_HBg{v@=A^ zThIfo$pX`>1ec zPJmdsTN{U3{;+b$P3&X{GLdHIaq4IrvhI*#o^;|BeMC%#_`W%%3#7zE?<<+`D1qV! zNpm$kM6t7^f7{Y6x6;zF=+L)y5=k&LOhD*=EIp-DtT)J8$iFP+6yFo zLIi`xW0J{3mR(6*i0sIYO(c@J?R8kzdoaR4-eat)=>k9k*FB zleh9t>0WXOLU4ykaigo*b-l_tVYX2pJB*XeEL`S{P!aL&qdZeDqr1BVa)1xYJaFu} zy@^$vDU3eII&uQj+7w0;>sZY(4TPkF$vJdEC{>na-6kXLOw8d&Gf^Czb-v3oh0zCD z#~@dv$>k*h7op0;99Av5lI6-C_QkA4%Uz&VoQ8rcPn5V)TcD;fbPo0rZA?}PFxF(x zI<`P6l}*ret`2yEu@UO>{4!hX3Mt*6u4J7?oQSc8#4>N)Tr`tGo->8f2U*9-1gjwo zd1kuItV*yawKz;+^g-5<6PVVfF!Fs7syQYnxFEMz{z%zQhd#m=Zx}k8QJ-yXm(pnB ziX*MRnxTVGz0B~PUN&u&Iu_ZB4mmI;0n_{HiSJmEF8>n&`)U~3*3i5{?LpiHgkFI` zMGD&)TPQVJJ|(*!Le{Hj$oxEz=)7+G^ISNR9jHz<`#}L4*MmH!p%E&2lCrl=m4GC1 zB(j>?!e#j~#W%QIz^xaPC!&BY&ZKA!V;=;seCOt@G?mOC%0~&V@gcn9oy$32n|QH& z!|6&N@|j<8EnJz?d-V?oI^Vkz*@>@k$_glc?sA58;>*X!tY)FycLN=}L%1`XlOTEJ zW@cg4Hk3KLqum?q(PZLkCtlq}$$!(^V>vU~p)HjrtJ2pvgBxkSE*k2FuaN*{=B|?i z>t@%9^~9&hzR%8~BjyJlr4058IbAWu&he}uMWjpm@8t#j?c{Sl1;5dL{_O=kev-4E z$ZXcOAA12sJ~^&5fGGMxG+6hiFxRvbA~&&iS6gbyS)5E4JzfLQ!HqRqfLMDW+pP1@ zLN(efmFBzZ904)4KCqam6pg7HVBz7MA z=4`B{HmB}{&qs4(-Y-W_K5?!@ZEDF{tp@QPv22L2SWAi#uVnk*n0&~HIy-C#b1o~- ztvM-DWjloPMe|G~NOUx7k1{iDtvXTV=EIXB>A_^Y7~mR`<4oVQ=%}g9sh@<;M|0!U zewiWp#JLi+sU>T*%IgA6HhSi^`CX90=#K>k%t_5wU9YCh3FHbr(9VeM)PWEJ9ZR4I`dUma@gc6h3$I~7^I=4tg6;wI+qxh)DzBIe>ty-UleY24SM_-yxVyH zXse30>TUe)ct2_RR%M09epWxY+hu%`ulh#AUs{C!Y5&q9%u&ZV4O5g=E9_; z!siJ9&0ghBzSts33ct{_MA26x?+}w+G~XJZL^U!PZ$SNMD39bbB%FwR=)phy&?|Q3 z0-Uz@0Cx3Dt^sY8-vlHzytjjZrodmi=XK8ys^<@byyV+d8guwHRQGXh@+Gx3)oR~j z0AE0$zb6xHgY-pgZqmm!v=&2FCHl9|&3?SpKPx0XS=_|)7pp;3Zf^3$e4XG!wXSw@*>y0as3_^UAFYG$RK3oLoOu?=|I>Up^wU-!BDXHQ6MK69r{OX$;2+v=p z{(WT2&zfpoT-4OyNShpB2!MtkaEWI-lmM4lI@uOnX*L4VjE}cS=US}!ru(BEG41#aiaSvkv6VFujqxp zCw;cGtcIf>aLT%-HNg63Q5Z&k>o+q6R{#;iN=>6Ap=wYMNcxm&JrOQ_LLnXvZpPxK^_IeqJ7&lEGGU^zbeqKX26rjLB2Lmf} z5~Idg=feO&P~{>^mz^GmDXPm>w}W7GGb{)uvV9o#goADmXK#2cG8RF3-42Jp9KopF z5jsX>6$a_q^cpeAp#4Zbh#7dLH7vS~6oW<1CJfTE={+(sAuYFrs%e)&0W6@ldC!p( z@Mw5sbXpGvL-0k(R&f-1-fBmgKdRzrK2Qm1xuw*a9qsVw=A)M|0cA8TyN>}+!6u@l z-*${J0bs7sAorGCXLAUi-Ve;Bmy~c*epl`Pd>U>k4T~P* zA>z^S$Y@#h8ZU{Ep1Z{Os6-6hVqM0M!6aoB?mYprs$q`_VlezL^2=185Yi`+s&U5& zBhUz`*|aRWP6WUrWf7FGeWKopNfmUgdQF^wOTkj`B&3rJS3D{2q#Yt4{q~cABPX1! zPgcvK`{Z!gsERQK$*`4vR%X&n4R5DS7rD ziUM+P+rHn_q2()lpJDejZWt}Jv1?s zfSi^^x9Q``%z(#VdWN*lGeV&eGw{l2n0K8q2AhmUP+r%%_e{w6)SP0=Xm0+^&`-Dd~XIs5w@uvnxl0&-ebJ?DtWrD7MUG-m^!w7PlMxnQx#SqsihK*K3s z`P?t_K>AEDF9s=dzIoe4Kzg>l=R?M)<(5!0?L1!;x*ukKS#8Un^TXp(vI#5dwVD5< zvw#H&X}L>Wu>L}LPpICoG#cjJ7LLWDUFWPW1mc=1``ljcRRBO5fLflJY zUGjD*h|ZU$T)LDQD64JReHnOMDt1w2qmIi&VURHM%V}HnTow_BoH_rpEp0Bxwp=s@ zNyf{|u0Y8q0@7={LO3#^NvA7{UvWaom0qswapmAuXs!txrG8Tafn_2bRED@KA zLsZ$Y!{(4^z8U#sG%b2;9`B2aL(HFE+bzJ5@MyRst8Ou(pk>zOmN2&rzZKk8RqP@a zZY_E1)7w9PY1HZ@o8JG|})tEgw&d>~T5g$| zcT&33+s@>Eg%tJM?HrCmNY7XDK85chb)WmY{BChyrgvq%ue!TF-#72R(@B{5<+Loi z?*~CnyVd>7?blD|-JsA(m<8l@Y5h_RzXF* zwu8XY5*?Om*j(B?hZ7qvho$)Ne)QXq0L9$;2;(C{w;3_1^hk2uN2>2OGHjhe6+K2S zs5F?e^HF$?(tlL4QFGIe27#9RXvIg@KKSD3$H!1VM*cB<95eM0?6J^@8Tq6&EqaU< zhfU^J7-ZCGY#1yu79oEI?Z*y}G7f#k<06k+mUTRT^^SLc{EP|oY0}I()pAQzIl1g3&nf6%ML5U=bleiErd{?9gF(W`C#z-A?cNip)5aR5rb&GnWC(F%}iQo=5SQi?z7OfI?K?k2#wAfJR99UAiJLJ`s{48 z$J9QD)|>>T&$)gs*>h!|n|1Erwa=q?o`v($oi}SfK+E$boqzEHf(s-xyr97ae_u%M zLV*iIEF9i_k)pB}BfVJp;t1NUFaEd$WcMYZ8!Q=Z+;OQu;HB9v-G3R)%S2q3`LZL+ zF*dl|%JT5tmp|&b0wfwS1D~{pdAAi}vB_D5Dz2C!RB zZYQ-}SljJM%WR(tEVlz$wH-=3-%)PIsCqkLN;TRkox9^c^6T#mUVP{J2KULj3vvGY z?A@iJ=DtwqBy`&D3P2+?wC%aCSPb8^9K!ONO?PbpN>$l6D}U#GMsxo< z4*-pjnoUqv-MIaJV#OQZFU@X9IrbaVY`5@EyDJ-a+&u!7kd{ka*|7Z{;K=w?Y=XKi z_n57|KPtb{szyEbL?o%SzbI6EN>+YpRYTjJdnOUk^Gd0i_t-yNoO_A%`U_Atq=c$T z=OLqg@hP@E6mX~v?k)q_rFsvIn11La<(>zw41=m}*>#vaM#cJrn41iXBd6JG*f<;t zji$p933VARli9e_@K7o`Cf41D5Bv*_h=%#wIf8(!hDpZ}B6#bJ=)+HcBgRllG#`mj zvGYi|eDz00$ulS*-*)8Ge1jpy%ruf_8Rc4zn)tDO z??!_xHd=C!M?AxG22hLE{z~+Vvg}0f&qkD6MAPVZ3l8TnbhJSq;-p<3pg}Q?UujYngW$ zKguT|4Tp%Lj%BwA0O-EyxWtt7tb0rli%Cq!DWarr+iOC2Y*HpZDOIEP6NVxBB4^>3 zQ8(#0kq=}%O22|~nr59RibN%#W*1h_w&*%BG#U{trzl9*s{6z-7`|yaghBNtVG>Z# zwdpZQX^%;>l1(P0sM~U~gAS9Mc0T#l6luglK~nn!w> zu>FOVEnneP2F3P!R3U{Z)=tXNRwrt#PaqU(Y-@JtDC5bPYz7!5AW4=qRU0UkW zyUWDpUKWSKuSn3co2FfsgKl}b?d2t_Up}}3VW%r>tth6b+vbXUD-mh7Tq&D^O}Ns^ z&={ndR_?IsbrptHe({#Ps{K{JSCh~%@3LAzyv5a>uKuwGaiMGcT@#&4!=n2&zt=(| zVlZsKRsweNYxAuG+2cA->)}&pzh3G3Qkvb?j}?%qwt;!C4HA=VsAAW9!)z|`CL2|C z*tn|pCM?PgH;Kg}p%+rnFzvW06sm7ppp3e4mrdh+)!YoT`erj~O*b!7GwQkpJOQhG zi!H8uY>C6bCtdwk#J3u}wer?+c(rdsbDQSd%5PiJVLQco+f@Qp+H4O)l>PQ&cQC(0 z)Q-IJI-Pd>S?W$=cbdD8{yQVzdGRi=_xX5VMt7CnSDCbiNr$_Z?VGOUz5_&}we|x} zQg}bVDA|kb7m=7(z4LBp%rZUpn@f}bx#jLGcOQKp(0sJD_UO^E=(0a(RDx1_YWCV+ zyrgP_dnWB4v)jEW_a9d9Ub%bYKaqe#(E~Dot%ihF?mXo04u{e`)Y*a7ho(LB`hg>d zVHzgQrpF+dtiw`sh*mmm;&2sKU51CjB4ri|I(*#-fci(+8_@>=yTA4${t|3E5@o}Y zVrq^IR^*_zBmX%V;wZF7xj$;mXb4@8c6)TU!E^0L|AEfk;ur{HBvl)ex9KtChQKsD zmho6a-HvU4?3r=!TaWX%%W(&fCp+F)f5*odzpMBJ02PyNC-`+jKPRj|5yM0+0&?2c zJtv08;b}H;O1YD$O!9-d(WH2-Cmrc;G9=+{Cu^J>TD#TB$EP6XRcSj#9G#Ly*S+hs zJEg?l(@IU5!yuyD{!|E46|hRwIyKicXl+mHG@Yz=+v&n{%m6_1O`q!whi6PV)BKsG z&)hi+d*`!i&X&~g*+tGiIR~J>IieW2gcSAK&gr|%oJraiUC#wQSF5ag)4B2K0?*ws z52KQP>&G+B>vG=U>w^R5qhOQyT#d#;7l{aL01C_i*b-1~S?dmW9s>Zw-sY(#o_;9s zo&-T<^as5Cgn*%{`O0am3Pqze!~kcNVk-(&h5&25mQRY<*Uj@Qhm?jT>lexg9kRd` zv}P1atN=m?YI%PCMs!Jvh~vcJ^tF0gJu>Api$6SF{3mj|`>kX;9*FsLs>fHl5PsBQ zXH5oNyS!%CANdA>ro2OaJ^Epd%@uwYul7rbf=ui5!SrYhh$utVN6Chpnew9;Cc7OB z+y!Qq?C4+4*mvZ0l<)NcjWp&#MUwFWt!g>J=GXZ$5q57FwKF$Rh&)m zjI^7AE*CYNXl(eYEdhpzLo^~vpI!vu)&$L&3+eRKXS^0KRE`Z~hmXg4360y_q;!8f zC-ZcEdh6bSg^N9=*%E^1wx*3~;+f9~ve~)8l9bY%XBRO<;GN_361W)^s8C8gWnEww68D~j zoC{LPRT%D}Ilw}fESv4+wjjm9-7g82cYZ3km!DyR=bVJOBME7jzeJQBJ0YHLQ}kFy z$XQn9LRJ-VHo;t{L382dF_e^!GiM>G&ID=B8@wv1xD@s?me2U7DI_woxvAOZCF`4? z@u9FYtCv6OXzuaVRcoESzPl=^zWnvv|D$l3F^E$gUsnyXy> zQAruFzZwG-yER5c^z=m105DpwQQ^DtWoln?I3ZD1tFgied(4MvbRIVgR`^!Np)|&o z@=eivOYnEE!R>On-r5smdH&AU)ER0l+0xS5%hG%5^qUn=8*t;iUsriq$x;b#w~$tz z-!xb@no)REt<-uopBkuQzpVb2Ki~Xd8^^ecg$9()wo=D+X^MON9w^&Xmyqq2sMm;l zB-402O{-V7CBcRD942Ghb z9MJFyla_HO04nuQfQI7Iw$+B>b<#fR$h2s)tBR`RwG2MiW&*kgEl)@$2*B}p*78o$~K3yL@)~shgkNP=#En1PVy=O6b>rUX!yw5dhvubXR2#AbSz3 z$s|OAt)mMY9|E!9)aJOFx5QO00@7h&2MorjK?w$-h)|D>lOz|uY3Kmik`x=o{to+q z3(#AGrFLaW9&i0bZxD1TLRTh@!srzh0k7Z)oYikRQQF&l(8SEnVc5cyl{xab;WxH7 z2HW$e#EW77_M&zM4Yb>mrIa33#p#MemrgpY|(8S^OO0wq$)#&%G3 zHk3oc>xdh*%9@x=hnyQ7_YZkeFktU8O-tvEm>8(qwy#4yXuDk}a+ zD(1piQOK(dx!^jy@7GqQG`tG`oTttQ^d0-;y)8($$qPQtbOGq%Pkk3 zA|$YZ2Dq5caLk%CE znCE{mv$b7*aDIJ%_41tHwFYdPFV_5P6r?KR`#&x5pxKn(mjdx??)l*p=C5BZ+skH} zClL#I*#1wH+=x+TA=uD?(&^OG>1s6MXVqa|X;DgmHy_xP%oMSZ~G}WRh~*3jxFq2;lGrVOI37LY6Z-(i=hr$~%^cqFYx_YI@Wx3k*Y=nq=v8$7D)Szl)6~`gQ7}MBCI9~v zWVbSsMzp;WkMV91b~Cn^M2cN!5=uGcWM7TluEYjn{$9DsAF)L{ZE(QhzOXd0vIj$> zqxGx6%)@0#N?i_Nyx1HQym*9Q=C-(0qY45uxj+-BxT3=G;%AWU%8B)sTNnzEGk;5> z-+6#S9^v5;P#(a5sXm2C|I2gS=Ul9xb1wi!{WqYZCOCy&hyp_eG{;HDuWAXO4-2|U zr*gmBvk8tBedx7ke(|2R!tG(?6z5GG0J84npZ$H9pbmGHvTzVXjw0Lg0&q56I++T!+$~v(sj%+cCJ)&BeX#0nIxkv zGu->#y_C;P2p%2 zixM)c2;8;C4jvVj1H&8YO6M{qJYf%ZV%LuGk?&}C@Vk$XW3CeiIKEX0#>r{|sc2~% zW#DJjIrBi#H$4-w%=0q9SqTcHuzU;CZ=)wLwtZ0(yEAGnxk(g^K^Jyun4UmB^JGO+>qHYn53qW$cU0rCyUT}xf zmySUWj1g5G)qz1POqF6d2A_g>-oCAokuCyAwR<*OMC79nYBaS9RT3;Av{{zpfTI#! zDTHO+%zpEe1jZ7I9$J>5Ob-b2{oZuP_f^^w>pJGFws=GBH!sn=2j5ZCCLXL5|D8S=pB+d zYtS|L?+Fsr=s+&Qd+kg`PqZdy&|LQm6YIUSv~8f;zEN8FRSf$en1b$*3M^8){^)^z z|2KyZ=H(cA8Y$iC;op>H7k{;CAe8KijHZgPvMtEQ^iFgWdM_Hd{9@OGO3nNRq;5L} ztH1{wI$>v)|8-Pi1z-LvqmP&z%;6GYe_gx=HIf-~d-i=3dYC$9G8$CosD_ajdPv(? z=~pxrr9loEdwxV|B(~4h8`*=H^c`t${0kB1oml@TKZ6sl7s`I1Lx;9$?G8LX@igA@ zlW=lH15QU;_y-(m;aVw%+6&amG) zhEHx592UyR-c#~(rgDeoag}ScAj^R5?cL;8W#XNy*^Sz;3-u^=edHL*9b|&NaK1-Y zc-Wi`d}}&$kCql7eV(Muh4WMtMc8#%U`5d!N;B8i9;aWo{G31CXI&8`^&bs)< zhS?6mO?t`|QWxN2+dT$yqN2h|_B{u!IN@RKV3D*aY&?X=aW>DZoO9)(%-cMbnGME! zZ?Lsv%A!gTxTg;^=W<#dR&#e-Zu1zhOXg~P-1`sOz4IE)MAI{$U-qS57?Syz(l^XK z^p;y1BY&u;ZLmZYDK%N@bkA6A!fw)Y$GeoG-DT3ibPorX0Iqd&XAU&y?QpC3hg+q#T-d->ae6Hc{Y4BFNTtQ|1|Kld(?Ln8*c>N<( z&@{Nbm`hsv_J=2cV{Hc{LCiUVxb6!}rA0+~9`(@im7}?>jTdhxR;xi6A+*W`Q4ElJuYl}Pl&5+@7Toh)^D76k59SpZ@KUi74b^_SkZy2-ohX(>+w z5kzlnM$S=$lBC}VA9yJq*dADK%0n!PTw2-CPhO+$IC@N?prW9Q;Oznoi$zVxFtvw= zza>ISrn@3UU3RNgh8$8=#4cmE>=tj4SRr3B)OSF&ZeA1#<^cIpcnLf_6H{>L0hvk; za%kOU;KWz=ZzJ4<-RdNCzY@5B;ZP5mpQp2yU}r`?@IL?h4*V_TiL zq^4(b$nVAmaHE46=-ZIpTg1taSqIO(YQaKxpU_zm2vsc0cb|f%<_-!fGD`0gWYNeh z?^q4KjZIFLJlF3vK*6^?E)L0u4-2o@*acJ|ip9br-vVkSvl9$?a8!_~RE3HuD9P-D zr)KpJGSb)*_QZ;oo&P zG+r`qBD6C0lM5HTkX>CX$(j9GBS}!(TKReesv!%_nnP=lsG3aF>ndB(dL-APzB&v{ zOS$^JjCR{MAhWL*lBT|uVDFIz*|oJcH%6s$^5DqOr~-lhpCpS04wwouR<8&EJRXa( zG2)OI*KQ+0M6RwIf}jN?%IM&6D99G{rKp?>2`8&R$Ac`gxISQ|;T8LHNBTtlvyTOM z)LI&(J|ThMH0DCWQTiMYvJ}?E_2QDQ<`}Ehehp{vKV60*cV(LLL8qY<$kLCh(5sG7 z5VL_8N9&m!_Cg2dYVsu>45$}fPMgB>)UOOJ8}De65-}!}JY;XK!rm^6J-O&hqNU$P zc^>JeXFZ)GZ8)P#THt}h!`?bkB_;mVQ)}58Inp-}P-SMW#$mmkw9s09&mM`W(t46d zRXU{+#A7|t=Ph3)x?_A%@HxF4lXs!U=8_!f6twDOy!6Xr-j=9k6#{nXurlwev@9$| zxovuDgL|T0$B5C~kMM79$8m}S8^ow80wus8TfV50DuY=U#ktu!D>3ZDmdm6|4Jpk5 zZ^#2~E0WYo7O7R-u5Ds5t8E)3+mn6rNA}Fwn-iVy396qt)>bDvIs*JP1;FStI`#T` zNip?h2Dx+bYie-{&7&c&z3;^Msv@J4`7aviSxvLTMvL&M$!IymkOoM%VvSfV&bU_0 z!V6VuCE!dbl8Jd40~0ikwJGsTf0h9;c|cQ_1LW-ufL_a0>wJR4&RZzbW+OZZ$34MbJ}%BcaC){Mi( z1tP$qi%^c5o;{p7O8@q3Tq67&#y9!C5h-dNs0MF(byoLO5RRznF^)lpM>It2dT&?$ z-5^T~okRkG??;sjo!%xMADYYSFvkfLbff0+z|pyV3{A=)qPH)K_+Ck%?Yd-{IuUdW zZtg8#3_Ep-sQ(y9e4Kuh4H}|X0MSJ({4`posO==yg2J>wW#o&{Sj%~JZ7TSmqsg2C zhN^mLjgV(kG|<{CzB2}SBU3;K8yYCeS&@tpR6YKAW%3V0sI>;jy<*hLXvkGt>ThM0 zy4D6D&mC@6<r@TP7>ZJQNoNicUoEqx~l4lowZ~Mq=kOI8te<=;tCXmh?8#AB` z<>__4r$kH_)P8aOy>C+jtQ6y2)-V^~4+A&7^C9!mde*M>bTC2)ZSHHTZ}N*)``#pz zA-Yq;ua{qk5L~HZ3!uFX!fXhfXm}rCgJa>5dv8)YK=nFesy6z8Oa^%)cM`MxQ z4}Sh(J_pFYFp7r91!m_FQz(-D+glL?(h&zWoo^1fAon&>AIy=6yM_&R?HW-`0@=BN224}-Nwkyi{$(DR-&EAR2WzTAr z<)Gvw`5Nq?xLDla8RJ{pp$hWNWY+4_aq)uY{T~S@L-YheoLvYmwN%Dsr9TmNP$G4= zCs}9%{M1N3t_A zo)=#wgdmjs_#Y_KV3x~_tNmq-#S#&QMW`JV8zDBw#|^PU$DAXRz#HOciVGogGNdpp zyPVL}5Cdz=W-$%QI}r(yT^1pb8rR(|yGlD_(jBXP4v=d-KSmsEUr-KH75Pu>e2m{}jy*1Oh_D~n9yz8g*N3BiMlJ{6TK>K= z54|WF=|)^_fII(=^7pnt?KR=1gpQ}op)~!u(F}BcL(AXn3`iyqWKd#%CzV`Cp@yS} z#3b;xoEp@KqC4-S{M~qB2SW*d1?9o{rO1=jcZWRPPoJh4Ta{HFB)kRNmNt6Je0kc(*N9(vlWO1y^#l({ z&vIG)6?!~E9ONCd9u#>mFw9bErKdc?9Qn%TsH?Y357DCxW9hW?k+4#7ZL0cAvL9%I zg(3aYV>k|*5j|f*^=p#=gZej7L;|mg+Frln2CRw8Ia+!5FKv`CnD2(+3x3iIxl!8yMv;+ksU zJGb(u`rdeoK2JMM$@q;Z(byiQez>jfaNn`vyz81dt7>!?V+UvM+OBVg-Cv3bJc1qX z=Z3m^@2ax3nDRCK?nO4S^6;2IZ$D772<_Qe;DPG~nZs(QON_pD(Yvrf8~oky+D(Fk z+6ihZw^mh|8En5a?RHsH9n9%ca;g(62uC1 zF&{8++KMH>r=K<9!`+G>$4Beo{~X9|QE~A6XPwXh-%42RQ8TXqF3Mt0p~P{g7NLLt zZxIx^7M@hKa0=nfCb#y0(fqtQSN&G-^XB~eQ-AyRZJ7XR_*ivWwD_mdMxkH!Pp(~g z!8Yk&PkjVWTzawJ4E3J)BEvw?M?ryO^uSO$$on_bB*sZ!J-vYKe4H*y^Apc0U0+!5 zY5Tuqym67YFbZDVn}qI!XBnJ!bOH167fWtw)LDJA)vdV-peIIZcRj?DcVZb6f0l>Q{NxA|*NS{9)s`U9e9!GSh(8e*aMEDfWvAV(d2G zEkUm@J?Yn}Ahht++Sd#)eYQdW)G!!-^X=+QG{kI+K`ya@PSj;uqfdEr-hAn<)} z^xb|OUu~Dj@Nl23*NoN(mlu{xVSWiU8pJ{3-om^4Sb}R7Pxiu4a+@sW*vSHw>tg0& zPW0m#tUAN9&vEc|l@S?`bikQ~b^UR%C$bdU^ZGvfAkynnVWH5Kmq)}E$hItj8e~b* zOrF3`&nxk7Id6jJ(i8QsulB=xrVi{ZR+P#45o27j%4K61$B|8U z^ASJb$p$qp4px3ZtQE3U2+R&{P7o6KGhJT>-Jzi7UPQmz`0?c@EGuLwebh_q_m&V! zSv7hWTi2yRce3XXCO}s(!oRsv> zAT0WiKVO6pMO8}MG?C0jVZX!j*~eY2Zos4;cj1b}UB;koqtRq6wr{?AlTY4egAvsA zC!w<*B0<}%+{u$sG9kzike#7N4oBQkt9LDxLJ&rEws(aYAJ*}WRs@@qyZFNugL<0i z>*?HQY5rT>Y7)9;p6lp*Q0$mn>li4Xu%ESLla{94875v)D=!J?o32_F5o#Ebag}j= zUcC_o3DrX=GN$9o@bd~2Oh`2J$>*=Yg@=P<85M)DsqBEE%3j7bp*4<1(kzbSFs186 z);s~*#P}5{wIBT&1qUHi*11*=&(|{>n50&VMeR6hk|g8bavR*H4~&=2qoH;3^@Q1E zy5rEgrb@AC+4;L4J@vQS6h16Cd%D&ymtV#zEC96ah|Rr_WQsuD4A-L{IZ!g8$WIqa zfp93#(Oez2NqkL};-x8^DfPE^97W!t!G&sfgW&FQ`p3|T1+9y#q~{#gW~Kas&uLeL z7`-q+}p$A$wNbe*sH zma6k;_`sY+|MLN1<+9ja1WK9qvz_~hm>t>pZ& zt`bgkDHro5{M``sd)*-h_&9AIZD9IH@dA0xXPFJoHeM6y#R{v~gX%E~153Ud z{!}Vzh2;4L6@8!cT??5sY~_AH*k4(tw#mh2K_b_qwy8yXjgWLO`w7{3q;Rt~f6Z8G zflqn$Fsr1z+spNj$#P#^8r}~OEB*QZXJb@sr?YZnfw@I#+{)h6Ip`h%AT_@deOD#X z=J}(UPsxCcPU9$JAhlouR((pc<8EIRwO;-rEQBfr7^~pDQ1W;S{Z;tSzD`cc1j|RtAJCEUbUn%1y`K zR=$+16Ex(b8AL%mdkVB-h)-Ux(PV?Uk*1*1ZC2H-wHJ-) z$8q)5vh&w755lv<*0Q)L2^Sk9a%+3gc>fQ_ z(Sv{-j(~b{I8rL##yWf$h^L{y!%O}avf+L)&KedPb0i+1V0WXI!wAiNfdHC>e9^x} z?;aPhK#X=cLn8E(TO7d!xbA zI)f!{f@#xbi_yIr8hcF8YTpC<0|GqrYz5s-U`-W+ijQ)UN$~qMJ5~{?KGUogV)Ig= z0A|E0?LJ${j6;s*W@v^^)d1g})Sk}ilvYfVexr^vU%0JV4lsCuJOvyIInw1tte~3( zI#~FAoi`KShtXnKceu`gCW{eSjcB76`USUnA(P~iUCJne##ZMv1@YG?E(K)X)Z1s< zaySgbVKk#HKJ@!#@57E+yE(aAKPnQqV?sT_Lw1+iH5X_4#QgSN0#A9fnLuw>fZyf( zJmG+x5RlUEK{%wi*#zB;Xo0*kfl7j$7mGW@0v%KfAyl#xN+}9;q?m|d&@N?_p*b3PA0}o1 zN~)6>$Y-#48n#TCb*(;K)>{Tz1gN~KA3}K!cWCRA@*nx(HcTonDR$Ci*MGJ z0Ss#7lR+N~D~&l=P>VtdQzPXb@st~GPr2X{JFn)u z5eba4TMSU@*AQ+Ld!9iL)b4>cS8)L|gC5ZeK-8;*KsQi--J$41qYx+#ltb1~hx)QM z7P~7K6fg)LlD9Vd>?GL zp9rYD?W``Nq+ulNj}=$2ZWjwLcw~zv-RUAB0z+UYC~Gy0%Y3#RBv3Ew!@O#t}m>bhI3o#p?2X_*H*gRB(#*XchYqM-kx7bebQ z4>|UupXq!6(eIWW*6QsCApNg{in!tlnz~XzugJmUEEpM6JfClKVYF-nA37Z-S|>CI zU0?G1e%;#GH}?IA&v-d{Jrc|KJMAn@+@D!)~U}5>*}`X8}pbLqe?24rpL4iLsz8&7=JcYfO0u4%1?& zs@ozS3Aq5c(_3OUc1P{S@43*`z!xw1e?(3bFrP;w$sYaQ<|vGOe0qh{T8{#&ByaLq z%~Dg;e%g#PeP{hwv5$w z+Y_wa*~eD+*m?f>&<^wy3|~*#smVK(9Pw3*3YN9gOY8UN$PbK-x`#oma!}Ta%1DQK zCGL%6g`rmnz(C)>8dF>aa(Z%c-%uciLU%nhVKtwI7D?qxtILZ;?F^7UZeR`1v(K=j z^)!YehbAEfP1vx{mUkY*DQ1>GC6G^5?W7Q_q>$yD*!gF<>SXldk3SSyU|UOr_qVWK z0U;`Euswq+rQjf5#RXX?Auv-JjxEkDD{E94A+w~hSLW)2qE}%dy~yj_!VA8Fk8K-M zC%!y9mdQ*`7wV1>U_;=BpTzBy!Kqv>#uZDe?m0TGih+sNg$2>VTjk>rn^){mHCicM zOcO-VMuJXT`_xmJGEA*DCe{|2)SO9?e!5-m9QiN@XK#q>X|3e)4L%OOJPsl+7zm&<&Jq0`BOW_+5eW?cMT^mRGil`MlzwQYG<-9^I7+`&v?9ogu!}AOhaiiM(##DCGz{h zzc%{w+)rh3Rc7G~mgn*eWYGq8m)&8BuVQWa^wvG9GSMR9(B`dSNl2r~a_u+$kg-hl=kom=sPBO_|df0e>PRKoMm+CppYj9k_ z$MaU<00mYqQ;Q+jyP)>?T($!2T9>FCeRabUq&`LItlk-@^W^r=RcL=u=<(IN#7CQ2 zqU~|x1CZS!0o~sWYt|SXETWc4c&F@zOjhGS;eP!miD|Iol12u--rbNSdm}LElJ`>L z8%~Q@VX(qmX4=}g8-90r5S+GQ<&=yqxj`0I7tuzR<%N++BXX>E$2KmhdQ{W9+Y?5% zL_|E%D#dg7H2xS4J)DXOln=E=t`lZ@c$WxO2W#;U;p@?H3nbR5l+y|;Sp}O@OSFj1 zO4^w7)1?hKZc}M4bW5J@IGE4f{^t8-t@Z8gSKRRgu826#o%^nxNV!fv2ZY~?fpmox zjm&aH1IrV0=|;cu05AU8%@kAmdcoCWzYx0bLsAC%!{*~Upt+sePYujcVg91iP4mAP z`oLdB6W&-dxt;g~l$Jy_WuX6mWzYHu4(lNte#@eJVQqBna^^5Y#fxrpq$_#Ra+mqxml8@ zsAfL#VVMFBd8A7B2d!Nj;NaOZ6kQGhQp7miui1kGfQt3qCXy)sR)u;hzTePk0%}R; z%;{9KPqs^kEhQ)o8Auz1NFk3)L&+lN;17-`qxq)WH}!T}6_kZu*Gj z3W}PMB%IMfARtB0nQ8x8NnHjA5g-x%HQmW*YNE``0Dqm3@JZ?(=^+`-)JduCeZWS0 zqL-s2x#)^KC7Oaf*A3&w?{#V_k!MlH)pUIJj8QFjSa9 z4Kgyb2o@7~kG|7XnF~B}g%~`GPP+&C%<-5SmK4rri_Ko?=E-p47D;&%9#X3oa*ng#&(h8EVjNV^SE@xe;-q@Ja-tD>N)$>#A7vN&*O) z>Z(-&MIdUuWp2tI4M}3m=77fw+&cP*QdNkUJgUOO9)f`jTRg`Vr5aPytjXVDsT}2GTr1R6 z^c#$X*QLFMg~Mg3kvnBBnT+{-uTzC5I}uO=l7M1YnK-*_#|BdEf|^9by_U#nBC2#C zTua^?nOji$>7GM?5UwSc1{HHaruQi=-ta1`#<4uchoG2#BsdJ?3c1-SQo+IX?fMal z6&6S*N@rxPpFoevIHujEFdC%$#IjVo#}a~Q$;_2|TJe4JHSnq%lqF-jgC+nkdGs|| z;Y=(EEjS>n*?3hst$c|Nr^ZLq`xpD2>t7%L>)OLt)y`AJdp|mJ4LB8+4tM0aSyGSJ zL2wx1zSxz1X=$s4?vb!dX_L4$2Gr~*k2$BX%_BdfpQgAR6slu)8c&+e1cb0oibltb zP76CgX{Vu9BK%*MZ?r`OE^`=n6_j?Nmj>?B#N*nxcf*(&m**ql++OZ+>W#+y_K9Zg zhdZ3hBq6J_QEwMCl{NT4W%TmJ1HNN8pYywiOtbq)R7k-ZmY`4B^xbWIS?pPTNU44u8AHo>NZ(;1@ zYq)tyjZHkP0IuZHVbszXG_LF*xDl7p4clqxi@}~gcka^S%ABLJhEH0Bwa^hv>5ndr z#A0H8HX@a<#!pEbTCU{Bc^tQnZ@z)wvCmUnzp-NDE1A@vWJDE8H?WES!mk4YDPraS zK;$z?8k$(4IR(msWr`EAiZ|628exhA*N#7EwM5MsSIMg#=p?oE7#CkZA7R7mPFvnc zJovB;hNZXFlP9z?nfrY7*xFlGY_J(lkmffl7z}JAfCDrEJ_#$Az%%Q@rVH}T3vm?= zo`CKk_txfF;5emALal|tpi1BfY!&_AZ19r>-!kW<@&g2@g?63&gU|<7TBv7Iicu!b zAteKF&$cdJq%2pG17&6ET9|LAM@$#DOW%~U^I74KAdI8V*0d-3DY-g)w)07}xHI&( z^EzKUKW@E3$Is=Rz#popK6AS<4DZO;In>jc@oyRf)#?YnsYNoR zkO5e|8|Qp7Ro}jIJA0$+1iOJvb-LhuGi3%9oe1iJLc$we#gV9QsXLawin98=bTks* zBiK`4N{Qb;WshKjLsmY=pt4=V*SGz2@*l?J)9pw^BD-98lOsuMS$`xiMP9{^d?Fk~ zeVCgMKxe~@9%b-_C{ZOxhJQlRfINyMS9X&^o6XcEsi3qbEei-QX!v4yHSLQOg{YUV z*%`5&cJi-5_@u<--n#sG8_|p&$wFysonA-nR;W5w6?t?;) zE)+EA+hg&8y}!#9gjP!|K^D{SU|(w+BYZP(bNQ3bY^TSU8#=*84QX<5<3?Rv`D!1bNMF6QDt+>r|Ze={V2%AVyocL_6`xJfA7OQOp+- zoB39Uxq&V}P+OE`!?I5yh$!?zKtbUz;qO#yURh+PsF$ZH-bD#Mj20H0O?YacfLw*r zKn);ZEhtx8A#AT@XdRK5JpOuZGEF3tsc^{nLL7E< z_I4pti;4PdUbac3RF~cKxWqnwQI&86hS?fZVbQ8#yZc@m!hz%iyDfA^ukZ2Bpqe8~ zAlq;iYV-lkc!B`R;@<+Hv+RdHI^>r?H1*DeG1_QAK)R3p+s)8*B~dPQc5t)F{2^T7 z^yA2}(PBX8g_6kLCLJ6L5t(uo--%-<9;2&jy_X@i_f3Vt?Y6KuLNPB1`sh}2&F&1jk#ooK8@@F~4>K#^+7fU# zWz;s@H+_vb3=CJoXj84rKysx_c;3}6iX63kI1bOLUH|SciDO!_Vjq@nck=t<|9O3~ zuJDfK>Xtyj_He|+O(PlgR&PG%b$RjXQTdJO(32s#Pucx*#OCphS!XXrJ_xqhEh%D} z!pjfJrNrY}?>vZ;?=_S}T=0;@*79&(86()dkPyPSKwE^$^UMdXC3AY~I+#yJ_~|d- z*Za?0!+$gNVwZOs^KAW{u@!P|WHw>pEmmtdH14++h>p1#+e*E6(d%C+JRfQ%d!7@) zBg)9*B+uX1M(;D;jw8NuglHF>+7tG7(c5wCPoJjesy4g)bwc~q*U1qnYwgN3AjCfz ziIyO{YyzDl7w=P2Rypm7)J2~6>-v~1{i2xF;?p6eYi1$43m?`Cby#m=aG9c= zD|4ejQEr&5`M0bovW~}2$+pxg3m7|GH4XWPT0V^6haK}QZwanB;wmR`+>F^0K?fXn zx876MXI?r6IW$gGWLO|z6{gB@sRJR}5dMWQXo%Ss2N@FSVv+|0VH8iwfutl|D}-g; zOujf39ZNb~?;KQ)Kymx)N2Dl*@tpBedL^1?SMN`226tP$A^~-%m-F<}Qw?g{P&?pd;9v*@!F$Cg$FE7oCDqCUl~efS%#U-Ld_oU zslz#LRncwFfXz&E`vU#m+QBuKJ=@BZ~9N1RBx|6NKdZ&Yu?!dhs!alcme^iQ9ccp9>a9O;Wqcz4Ek>+S#JsYDIA@bdz>sgL|k z2~?JIp;Hx`2+Bq?FG$@Vo^hm%4E=!lK8q^bUR)7>HLak z|33`rF2nLSn`f!?SuUL~bP_@zg``1S71vjKshBCat%=snsT<^+-Z(#kw-Rsg4=B{R zA&*oF*>Jsx3wWB!co2Y!`P9M%Z5KP~DNTfGYeUeVob=bEBd&p1P+z%Bb;S30K|%bv zn+?Mte*@=qn=C}CV@%d<`AE{;DBLSVvwrj|)t@=6tjRKEs2*v>2@;v`_eqUHMBdi(yXY6YN#}i>&$#f`!Kj{Ab@Fwia zBbz{CbO(Rl_wnvaCC+d;%honY@t|L1_KpTy5?RXg1}Gzc(VH`&%Hjt10>cjqUOih& zZ0=?x(l?fS-L|C^sO1mbUF8j`R=Tz99+(KT^xyz-QU6kdyyDLtz0m-rGql;%r~?^( za6E!S$E**9jzwA`F-UqQp?~;SflVfCT zFXZbd6p;B?tkbB5d#vfHGNyeI#odVdhcFI{7AZ+c7ozCGp;pt>9ex^ zu={X%k7PzF=wV^!eR5=}U_JEi^O5M_XGKl@W$2$r4&%f2fQvjKhg$$%W%Hf836n<~ z$bWDoX3_VU4ySQp?V4F51i^aB%SX<_6E<3}lD1g~g+#knDn@A6gVI2u*dfG2DDki* zn!~<|tZS^;-U5msRHt%C>RbV_<(!!9Mfiwt0H@5^XUj!NIqBtXGqG0qZ*<;>up5M? z@IB#wvJ{gd#=<^Mw=Gs*&x6+tRSxfJo%XM!3rXcrf;B0r540ti2~IAqA2`4>_%OfE ze?{V7^*N2B4ZR`Ep3C-E}pKJ3Nu9jntS%CMd=+)+A5Uh zaKh1MyqGsjG?CscQdJ7NTE^NGXrWL6gdVj#+$|uWpu+1Qv-lYcqOjI zt<-8*;Xoz`YHp@L`N5z}d&+*|1!`*R7OnuPnvIx|aG1;RP-s=eby=q*`U_>1sgQZ5LMjj~6Y`6t$95Koxp!_)j=YpO7l^B%tZGZ6 z0aE9D`mUOW681eLXSLthDsbDyUC*3;<9e)R$7#M|ouyK@-~0s{Q9~AKrCaWb6wxmP z6`tx%v`<2AlkN0ZY(nSjknn@};Pd|-n(su;54+uIWT$6WxjVY|(F)^_RSJ**M+P<) zUFiN?zae*PHGF~wS11KW;bd;vQ5mS)llvNrL!|ku-a!)2gviXRNlfaCvbS}nTcm8@ zy>{{S2hu}PUUir0+=(@Z8^24}CaH$%gBU&G7xUm$EVJ?z{^I^(a3851tWB#KPMhm( zpxK+wb0O7yu8=5X*u{++cL*(g=D9+R44Pm|){N(&HmyKc=#NEh1N#glL>@inx7XMS zKFL-($vcJlfaYF=|0+^%(xPG?isHjdl;U(Xkai_O-An_E8kPiI@Jfhf?@B1>+5L$D ze_4>|Y-l1@T~As@WNaGgZbQDvRMvOE$+YqKkRWj%$%`PF%$REbty)H&9A*A_C9u zB6LC+0|NNN&xWmT4j8Ec|O(Mlbx1;Sll(F z%%C2ZM<92j+3)WAJWwBH2`#iT#|F+E`lbj3hCBhzoJe1p zXKckt=mCVo?R45`qTd*QXoB@CeP$w>W`kasvE|s$ac}h22f;;nUPxG1<+AK6t04ft z3KHqp_K82rT%oz}94=!vCVNE5Ib**=pD)CbUcB;9+zuFty-sCAO~z;6+kbXl&{%xL zt^?#cHIXB@v-BSm&HnP_Pb$uGR};!buK2P4JOS8{1uMkh%xKp@Tj&3~L*pl#FYS;3 z2y=jRJ_YD^ps@IElT{~+_-?(F1AZDAf9_lPSy|Q2B0P9t#Dto@5DZ`lqp`3io4m^$ zAg4l3f%Q>5Tb4^F)^ZY<1S-evev>0h40}?ar>(yPJ*i9aX+NN&kXDQ=T;U|T-xrVA zV+89RW1D+EwU4AN*aTZB26`C}&X0N@81FVheV-A{f&h9_w!^FYloj#g^s$;%lf`aZ zXBFTy=r3f02$HSf=`Op3s#AVu1AtsI)Xp$wgJRuj(gx4h!Hdo@Bq5D=sjuexj{HeI zKd*F}!@kxCvvk~m7Lo)8Hw?>gJCfRydmAi^uZC`ZJzbCo;_zgh6@)BO*y{U!#Q}h{ z85(Y<2AQWR1oY6$De{um5roP(E{jQ|bYaT5rXc;EiA{0v?c-30iVA0cI;Jo8>2nNY z9@4F89pg=dGju#P8H|)#p{iwszNg>70TXNZQ&y+H=6~m}Sq{d^OO7ew2do(5pxIbq ztWT8gc`QNBiyYxi)t0QuFChXKG`Dspi0*ybStlhRC_H{{j&)&vL~#-f3} z%gU;WxiM$NOz2y!a&xYH8v(Hq!^rPgm9B(+w34i7B>TyUPrwOFlF2_Hat@Vp_C$1yUR)cy*Op(I`p@fkmc^Q`tA{y z!(zOk&e1csW}~c^c;L~;p!PPS8Z(f}Iq1OPus-yzo)}PM9mAJqCiA?7CnWa-vRp0)OJ;6(r#l2TRwcq!A*r!fOr_T@={q zAsu!fG7LH{T*W(+r9j;2LC8{@&0^|NO<>=Ws2C#8V3ktArvGI~(;9n*bEQpk4yp-v z3OMQh@3I}Nbn^ak!OmLTD9VJgsK+j>Z@fQ?JABd~qe{*m8ZWw>w+;bEFojTIQ!qF5 z*#?w@Y;Y;JhbU|zRBczL(BOSfz3HRTux!)yca*oU(9&(yo+)VW%DAEEg$POl<-kb8 z^#n2snsE0S)N^sz+LctUf|5x!2050#&zq3@ZpY-Ge*enMGK%^L@1{2iUfI)pRV_Z@ z9*o?b$#P0Gk#Dq$lCOHaB)+Q9t|PuZ^vuq(L)bt-jU|t;IatSjyrCb z`adPwjfN}|66-WEQ|-IL;j~XSdYJ_3(<00X^kNKKRCrqi5VhdizZR&D(PoE}6;^XN zFFM1|7p(0D7_`W;Q^(L($f_|i8T-dC3F9n=i+N2yseS!f=Qwws1k~g1gAQej+7m4! zX$&$$p1*4{>??A%J~)1I8F7Qr40g;kP)jZwnT9KidW|*95X&C@^>Y6hY<}UzyL;i( z2dYP<7ja{Yig)m88d0t88S=-|qYx1aThbc40NP12k#P>ZK=mk#ja#B!Ot?=GxN`0sHJHz2Ytfuh$>u@r}Vz3?zfddOE64}WVM`Md83>#!nq2!YDt zhi`SMS5n|Kn1b5_vhLazbb%`BT4j{2A9bl5Qqwu3Eseu-6NOGlfpM@Xu8is)y!kE8&uug*)-xCP%G{ZLy?QVdiN9=_V z6}DT}^GNvY*I!oFs6GWj@!`0Hc`h3_8`)J1lG4!B>*20W8Z{sEMP%<>d{ zGaQaYy2iCeIjwFki&7VJq5~9wfh|r<8R~)g0u@1{QpQTZ%o%dB`4E4+7Gscb2FgqT zt%o^MaJ1qJizn)E`+)PEFf;q{bdZk~_Wa?mL?3^R|Ixc(o}jU7yd<9d(1Y8R`}ln) zolWN=eWUZ*rxC7dA174>V2DF6-TRh*srv2FVeOT#|7oJX8ttk!IJ5={vE=%&htBA* z$7%Ys$QH|CG=dp3YjlzoYTv8LJxRxCZ1KiDE|Sz7y3DE+5FbffA!i0sbRvQZdhJ_ts#I&GlR<5Ct%O;0&8rF34HUIBDCTebqmG3kmem6fmSXBh zNT!%m%j1$U)P%ff83@omN>G$@QNdJjwb#F2?Dp3OA1LPHy5pZ2zK;9>$#HL8{=j+E z25dNH9h7Phe^KD!6}F}P;F(VY`Z|drT1dJq&^4Q236a9)GtwLyzO+PQ-)QuDCcohM zh`wcp!vphjL0m3(|2rsP4Fj7h6IArYRd6`>*Hy7w4n=-AlscH%45ueWX{o|R* zhh$>ZlZhOAejMtT^6lq}%|&2+Jsc6x%Z(YFx#>ls5azDdQcrQteX&hu%0C=qlg^tF z&ehD+XTiq5F^zqj07{{H$(S4ma-mS<^P*mbVqsfe4+YU z9tT`|PD6zq#Z_WtjEIIFg$Yj2%oOCYf@TBVhe7AICq?N$5!%=n8OZrGg=EVZPTqol zqwiiC)W~c;KS?eIXuD9vkGntARCVvS@1b9Ck`wv>c{glGme0^{*@`D}xs<2OewcHj zLr+%Lw~@Lhk|5=goo~w%DSx}{%s@F~kFUuC>sXY*4n*LcppP(9wAe`gya@9kb@1ty zrQ~G423s+%i<~mnXtEhN32Qovnzm>&&i)R(6$^Ggg|lptl$-#8qjZ@=d=f;eGlq+l zc`g5vDY>vpQ#_p5!a$zY&WV;7w{}9IWjD9Ts}*wNTFM@Iz89*meYZVmm$NK$O34(iNNq``+AT*lLvaM*w;IByO4K&3*#46rNsxFUDeEy9F^>K{B$jGJ4 z36d^B@y|b-5`}-f9;vTn(UN0@92zN_9@uFWf?jr6p3JbGO0uqQtXhL;l`sO{NtDf8 zoZoK^S_#Cw8vq2dl6uv)ElOc$YfK^Iutj3pNy9)xhkgkXps^Jl9E|N8e1qRyOwc*4 z&K*!&4`!QjFxXeP28tNFI`g@C1L=q>cqdZ*MAyPUEr2&`+0!<4F5~A?^YHJ|YxTM@ z(o}h$D;duFw5W5Ej#4@ox65!*YqNld6jsogXkoj3|A@VuWs>VUsbCKqh$+g5z~Zmp zCH=&#RZ5?H$}}l(o9jt#2w!qL+^UYa?rj*_c2~^p>()6&h9dU0l?pJk&;gJxAQ3l2l*FR7 znlv&0#8AK;*h?y|E#rIwM*LU}WDzCKknc%C?Tnp@I%3tn#mCJ`zL@Ihe%>vGlj zk7hdiN4TH9n#1oV(@lhWL^pg!wrfGK znm!(x6OtA;b+p|7e)hsjj=W*?O?}1w5W_KXiiA%BirlN|-}*e6bhP=EiAg2U3{5<2 z0u26l&tH~bUXER|8(qWs>>ffJ9;85PR56$9#+7;~q{*MmJi>l(sAX(BwH@?pibAV+YhdWD1E|xnHp%YvicCMKm6^ywuw1kKem8H zE;JsO1y;>S(0y9eT!ogvIYGLdZRwKbzRZnN>Bk?As}y-Z--c6|BXicE{^)Yn=6rz4 z@xN@;0F>})@*n|nfDDb~Gd|3th#E+OO5i*^>#W2NiOb)s`qBS^GM+5;!pW0`NK%X-rl@Rq2VIoN z6>l;emq+8iQazCc_i)htVfd(bhv*{y=^on=^N5pwb_8Y^Xnlf5LN&b-$zRk%S$>Y$ zaH_=$)%9cCclM@ZwQEfD>7W3R44Ya=xxz0vmn$M4ybxcnAn=k5@aZp2Vl>b(+eYgR z656|`Wy<0;g^BHf+5O($4Y`VYIpAmVgY=(SU)Q(sv%6#x7T0k~L*ocg*L?i(iwjpN zs;~c1Mr=d_YjrixXXPf6s8g;_3E&BUSlDGlOMX%dR!x2xGJec{IzP#p@B}(6YHyiE zI`ye!(R4ex6e~IZFg9U`9IdjnVt23^e8HU$oXHM$h>mtb`*(a9;&Dl-AOkV%G~v)?(wODdGP{5DdJ=xI5}J* zu$eC_{yGIQ$&E#96g)zN^wwwT2Dm^x+QCg*TYEO)orliUHMQ*IIDnUo9G&QGL=Dpq z(U(+_m?=w|f&DQyS@jt>*gJGUFoq_h`_9?h%Xj%d&gSX~N5ja6uG(CLBv$vdS-lJ*L^UIem z>N<^t9N=J%CKTA{yhqX1mjU`yP&t4F)xU9_ZTF89TQN&kd!=ZRCac-v>SjF6H@hL- z2^`*|j?z=cyY5C(T%9uNxWwm$wu^A;=ze)ZE=bogmWLI_H%ajam;WcoR&v_ZTx*77 zOCafz0kR%_E7Ut^Q-#k!w1NN)%_}lduSe~tURB?7wkdrJfsAV-aY-9Y9LUnzWfyfI z{b$3Ha65tA6QcY*0eEG}(0YaK`p%@v-4Bk&!?1EQ>w9o`dG5BENEuJy+^S;80TS9= zu~fZ0`WVj4M?yL4!QY>Y57>4?lB%1bjUa)N&{3X=3;mMTGL8epfB__2R8*yaeJg{rfDa(R0g znwJWuQiYP(&=3WJSGqf?%eX&MPv;cJXSEelt=_ck=qB%K<7mCnmY)C_RdgK`E7L5+}SZbCDXkj$1P?K(dGBNc3A`GyV~vwf^N=f|9&%Y?S17N zD1zR*uSjwxmUq5qY>(LczM_XiAtyE&dR+3+cSszvspTmHncDhfK&N9DC~HJ?i6t(= zpYVC-s2qJ#^Ku^TV4*I*RJ8DRRf02e(_Eo+Xj(b)*0Rcw7{R|Ds&#e=V1q5_S8mO` zxv6QQnuz?tyvhjy1qOoLMRj@0i1P`bNQWq~z(q|`t>upBE!#&(GIOJ&Xl9c(#P5@C zOx8;uTy;o9#co2?TryUXLyYiFPiWA9c7=nC-z}2F%Zh*jabD4)UKyXi=1$s$9e;G% z3f1Y-RK`Fr%l#vfT`V;9qw9IuCs6=?YAq@X_PSHj^JF3&HK(dl(~kXU=eVL?`#cOg zkfhi`RBTF_2-1HWnVrI=4a^XJ4(Ypg&D(qP?ahtHlAe3b1(?-E9eQAIIN%NnUBs}` zvka^Xfjckf!XlronHYpkQ~|Kw!7hMq8-X@ds^TP(4vFN2nbGriQ~` zaWOnSh)lbJz1z_9zR%`A=L$&}@HRSoxoPtG*2OaO`Vg|%?{tezm{NEetp9!p!jpyK zN996XM(S+Oy$1{dg`D!H)VL+}7-%!8Ga!kmr3ah=u1s{YAxnc35@{Y9$=SRTC58z*o zL14F<=VfQMS3RlY+r`EpKG%iGd)q7^$jmQ*r*&TJRkY;dlu9%rSSl|lc$1~*R6-2-@^wLOA6zd*KrC< zfGztC8DJH?e&E;`>>Q@M$gsDI0`qM_l)?TZ8e_$)cvqu{CVZy+gGp?!0K7#Zc7(U@ zBQYb)z7{hKa@pE2fiwavqQu{7N`fB&d!$SQyvryx-(uVd3Azg@B(a_XR7jk_sDx66 z$Z1DMC)>KWz*UuabQ?#fWeEs$Zn!Yqp0-i-4dzY4Zhx$ffRR}k=VD%ncs;UN)hs#{*n@! zq0P>_@sa69%$L(BHXroh>>F!#vIVB4@~a_5P?i`#!}kfx#@t}-3&-zB;ggN0zE(~g zjPJBZEE1K5y%Lapb@0nrs$ zFzrb|&$;5&UZ#P*uDy)n+74F#;De2s4O4f;qN`PMp~uuMHG8KDRya;Uq#)0ljYF1Eoo2qJVpwtnky*ZAFq;m!n)FfoQgcT({0N!5pmsUe2- z`aPgru{KX_VRkz*4g9DV0Rm9a7=b1QHh0U6A~oh|NzvBd3W+NBk`?n9Nk3t?RLv53 z7ae<#+;FaX8>q4Ea%g7p%UdLBNqQ#hxw^VZ+ib!RJpTQq@Wai@smWXZWcT|Vc5NV` ze^kV!m9`jip^na2!=rc?9ety%xW*XiSU9oUn+qyzK4+!H=%ncR@ zTOhJe377ZkBTo`}I*b{E$sOwNZa7-TcHs@hLwB@J0H*eU$(t*FmB{wGB5plC%HK18gV)(#IbBmzS|%#d9^h)(9b zUIkH3#mt)Hms~9xv`5KRnt=pkbFN~6Fr3#pr!VJP1>s)_iH=)T^6N``4$R>`$Z}yn z=Fozj^&}Hr#Umaz3`HXXTMw9~V;3rD;@Uom%xkzF89&d)=@?(d7~*?^cXWRtO_xg#+okZQj1t<+E0fF7)R2 z9y3LE=go&lRlY^fvgj{!*E1ltSd%)?Rm%DZ#_b(~Te{IJjFY#db-X4yK-P$ywC=5C zLKNd zjc|T<#RE<>K>mB~{LDuIYu*1-f~%L|X1)N-bIcAz376F4N&w|tt~!Mhm~#(p2mrD8 z!bc)Zn~@DENE6zEwG#k1vKq)m*u@sClqI%N(}aAU?ieDe8`co{%_!*fkt?Jql!Xlm z%Cni6BU*{Aj|N>qHRDy}FETz+M7v#{W?EM+S%9~a{JY3ee&tspPE7!Xj5m}A`bh`~ zX0@4Pw2&4)>M&H5$^wotM3BYdjK4|tuX664(w0JOVtbpsjMVEgYz(@JKO)_;&ZZY!`$znzxbrUY~efPPxt z3hupxY@J?16(w9Q0nlb`ua~LhAIbp^&+U8%emMUgZgc^PmLsu{1s3a;$Vi$5>|7q9 z7tuw0^oEtYw&;8%>0W(9n-G((nAmPE(cZKp(G%GU%XBv4f7VWFF%PxG4`OGo(CqPD&q7DI z9qXgPfsiqb(eQUDnK3$IA&^3Tj=Sb+LPC36bp3t8U_@}Y?Mn9A3yKX@EJ?CtK8(P; z*5R^q90HiC3gdFBsR&s}o5j!$FTi(uiE)QGdfvAC-PV*wLoUlO`UL%~%sqKo>P1GR z6WZiZV>I@OV5lOiOn&X;JPp*MVxetKBVs4FQ2v+fVb=ADi{czQCUX2{^u6SfOZ<2r z)ZW#Sn%IJIN_~2`B3g%OIlWiMZR0b+M{qdM)jp4X%UG;qdK$0cHIPh*u1+s~ zK4(3mSEKEbL^u?x6CCnPm*>xWij3^(6PilDl&?xUV+_ot;m0F3Z?SX7xt?Cq>!+MS z-_JE_`L`+-c8|W54@$(GOl7~9)hy@RgGuu#Md8$%yr8f_%-V4bSSpmLnhiA-(0flV2=@&T)CT`K{85Sf-scvpB)LW5gKh|Dccrju5r z2B)rNrd`e2{lAuGnKt&ptv^MI1p1zFcWaOl-I<{~xRIrW0&=BJzr1R0i`#;X&Yl$p zt-Epq1?VmwWWmPlKy%s%l8%F9SmuHQ(iFZHf9OcWl)LLBpog4(H7DOuLB0=iHDA!B z4VQXl5u6T97E=jkb`Q{?M|b$a7GdSu>NZBjh;M;@yQJjjyv{(ksG>KZCK z+L%WkA~FIX1T0)a1cRWyDxU8&zkIoD9C=Vb$)iPtP~sxhdAeHNkR4_tI<~1eqDBfT zE*&QLXBNeo0%)JrZb-;b;gtG~t%dd!USNXYRpxG&?GrvfhiZ|B61zpWg~-xNXbWoe zd4yA2SPTHmf$ukUDAHtmW|$nsh00>LA10Vhl>CzErfWC>Pd<^kova?;CcBNLd(T^L zT`K=M=u=h|(BRElZAC(MlKb zZW74G*O3KYG$nr%t{EU(Js=spWSRAO{PlCkn!DLi+A51d+6PBU$twhe+@gR$vv;da z0~O9WWA^^NquH)SW^u^DMjf!8p0!eB@NG zD2siA6-{Bd{p80cbVc-PA`nQHC=(Ig?5XapnWA(7z_)W<7DN{cEmnUrlLfRhVAr`9j6k-H^@)+mJb6=?FTH7g+a-mQL-;H!(y17 z=_cZ5lqshc zn^NUd4L&d9b_2K|!$mj5Z%*gz@)vG=bX~LYQ&S7=sUyb2S&|?ktox5MP*X^>$x6Jf z$hJXdlI_Kex>(OHwAZ054^(6>x7`V9EPv(Jdshb=PmeNEbtQtt%Hx9OXsO-qudw-3 zU8${=S2WAvl;hJ&EgSO0kUw@H4Mr7q3&nIJ+%Mm9`G#0YB#Ff~XwiD5^hm}JTwG>B zW2Y+?!ELZk~ zseR+Dd}{vC`k`FOPvFLIowj>6wx!+I20-qhUS1F9iIw4*F(Hc6u-=+j{Yym+MD6UD ztbHkn|9@;@tbOeBf`|uR9Da7a*88ZIqX;-jvy>?_C8L})9xOGX; zuUzbLkH;v;AMeQWS|>ab3pTh84o~3plF9Qh_NNPL8qn=l3$*bE||Y}I`m-Iu4p22pQhD${uca79b_ zFD7FnGIzm|nOn$n;#d3WcXqt}KcYkA*4F==K(50Kli{e?YHTF(0a;}GH|1-)6n7bCkZM_gC@z)UTjJF7k z5dh|{z`-)z7(|f@yRmt=?H0~ZsxK%k-49@&MVCZ8hm!?uw?Ak(N!#+b`PQEV4NRK; zS}bh<%OP!t1>yC96c z==ew|Kas)N%#*YcetnLUjbhA42@V_Xa4)=8X@T_`pYot!2{tR4A~+^xj;mfl*?=vs zrnIr5iS&qI$h|B(JD9z_%r-SCdqtp(Ft4XkD|ChXijNNfHmW>rN{$l_Oi4;c?6DnE zRREmmQ;Ryt%^31Ye{+ohq!FfCB0{{D7#G72$#C*M{2^I=mtYlG7w$iWc!(PH9IEJ< ziH7bT{8fPQ3lRC9H{g9G;;#9-E_u#S?&cfO86!<=;80c@=pH}U0j+a=F1uIkUw=P# zVR?^7m(O(do}14dgM&PnJQBSnuR(4Nb-!|Fzy0Ph_CAiQ6g(StwQ^X8A$cR_LP z>>NxaCVu-T@X{@3PfyT4`&OJri-)Z&YtCilzdn=qQIrq&2}er08yueT?2o}CC|)O8 z{{jZxw#B|A;J8moVF-&MRg2ewv?#I8R&_@EvEYF%dcmh3-LeAcrUIA+kJ7ZJ0|_{% z-a9plc(yUEY#hBrk8kQS*sw z3U$S*chwWbmECm_gFAL8JUXrJ7A$?P#@6W-V+>LnY=h*)fa)0k)n~h86w|p`&S#o$ zUjNaoK6~mKV_9P}Dv`h|l5MVwg^W%FT2owhi%UxJslnAwPe>Zgbba3ztlGHKd)dQGoGD*q$KU(2FBbDhp$wPJ-1M|S_%R?WSN(iOO|?KGfJZHH z!+Z%2O-I~y3+(_$K)AmM6^eeDR1|L(u$hhqGdu$?FXn9~scpa2}P|UK+tkt`*ufBIK~cpv1VufJUM?zCa@P0rKm3o z)nyx&gn)I{_dVM-2JBngfWQp)!-(J{f)tB|k0BF!ty_Y5qlz8x8GHg;lh#riOey|U z?Xz{hhc{5#@7YFzeZ1EpG3l2DWa%T1k|2}xuf=fU-mjRTjfFc`$Bk^WnTS>3ATi+toXHfg{i(5S{${5gUl@D-6g93%Hf|hGO2B)MvlfpTwnjYuV1d@o z&_I7V530a6dxGrxyOl6(yS5DVfwD;Z=dErBd9^fw5Q9z znvgUmF%sQPhkuu!PMNq;v~|2it5R-qK{l03eLU4({Zk4Rs_<1tLBwUC8qpL8N&?tt zVQf8lndOT^s`jU@6A)5|2L#6!Z1wvr!`Bxp!Bf4eyF$sowZkN_W4&ZlzY0j0$sz)LXo!CkPwN- zmy#lC=ww95P(LN3QyiRw_4(My5ndH#j5YV9LG<+A9LugHfgr6Xmqvn;ogjyWY|HD* zCsF3AcUa$v;RK6Jmf(LrBR37a0@raR1*P-AJN^kIq)J`}B?k;0zWV?h&v|zJgFlkx+DNFez~v zh(|KtKR@(I6Z6+n#7$9)1Sm_W^UF+Fz4)OdO?15o9iV|-&_5SstOj4oW#9Pyzk8Vv z!l0W*Y#fz5+Mmnk|20^7%J(BFZK(KHQl5D_MJm|gww2V1Q--mL$}(*TJgtbT3~za+ znH?5L3J@dq^_uec1HfGkMiv2MNEDqdC0h`rJXwXa$z=ENfBM;bAj zTvOE}0)ppp={nKjt?yI#%nkumG}tPc8;ho^pcZn+@ZNj#doSAh;QvG#ld4Q! z(Q3R@AhQNUmAF2VDID*O9evKHljec%HSf)QG8}GhiDxs# z#TzP3e%1(1Dddy~)Z2epG2vkyj2mm(><^n?suPk99D7>%wW)`_?UTd{g1K|#`0&-4 zr{$}+05`NyYzv-@**Oa1a#lI&O>X6sG&3u zLLfG(2KOmnDA920de812LTku%?SuGLTboO{t>r3(g19cT%7-lSzQg82C6X|x%>I6_C4$=FCoqv z1;=i0G~OT#(lV2{Fe)`}Gxy_Ttnnx#3j$D#5rI?N=~BzSc!$ZX*339_nzJ=7#hlRZ zR1Mc4lmHA0GxtP;Y}^Djd#rPoEl!iHy`nZ4L@$bRio z7$!yf;d3FKGmqQMgQYI3+~)l}7;mkh`mK6e{;w5!r$b~fn>9xd)KHgN@CvhxF>{3v#8 zHl5RR;A+Z(khqCaP_O4L7UB9g;d-HlQ8K}^SZbU7)dp-I`lI>X^#p2)C>Ae z{c@(@pmTI+3NAhedVDJ;AP}6@6k{!=*jUU&+hneRn><&j6o6gdBNEXo4Wv&(8Ol;6 zH3zN{_!se}77xrv+rVm3uA&jD8{vvJ{@OwH43l&#FxaPU(ZKxUs!68nH0o;L+V*16 zhSu+?Jy9y8Np(iEXd*&tCkuB@N9YaT(2j`HQsGla3EYW$SLs>8`QG()qCd3>nia}D ze4vAJIAYEDqC>-f*UpM49rATur!F%7H$}#aYg)J{7TPxXe5Up0U#j98C|0UnVKPKJ z1SXXB`8n%i$0ct=$Owp+o!O41Xu<822bYZbrJ>f!u)sQG5^)PjZ}~;P)XGqeG%F{c zm#bzg%wvgtNQrVMcit9AFL;*{Jx8ucL_0l4Rm3lTz~-+fLuS44=zal8NpN}Zm)u|q zBwSujpTs4uVdxDaCDN1^q5}X*KQ5C+(88uScsIIdj7>^v@%! zTJ9wB(z0QB0AU2n3NxKEIt*{#=4jj~#uA;zSZwSn?zr84_xP@GbH`cbwP$VZjl!!z z;R`RM6}Ia9;QIf(pw|9>_LzW4SLyW4LS*#8J>aw=_jocT>O2}O_UXQ$Xc`A5II5&~ zzf;QP_GDAFIZofvp;FVzTUDPOrh><^@}hRO4L-Arq$27tATMH9ci;TMJ34&FVH8Uf zT&~hN0sAtV!rf6rD%V3!FO>JFu*mdt6`&0U7NMVX{m>Xd7K@^IaZlw4#6w;;TPh_p z$26JdrnrL#dYNxrP}R3T>+4M-l`?cnRY*Dhu%v9_zBhNYeZDKx_Pnb`M+26w{0bfl zfi(i3h~Cz8{cgKTxM^x6y__?Z{S;-%Xm(R8JMvc9TM~P~q{?7r?8_U5@mJ^D@0j21 zMy&ZxFt8Vx0IAQAw8rE295G$I7n<4zuzC* zHUK70lp8^5obM3nexbOoBo&!;hMTtu>cJUpBU%iU1>${P22;@>4!J*ugAi^lb!^U7 ztcgg<_Aa6;brr`>Sr4~oHi(1#Y)gM<&-B@ba(Rj7rzhtc_K*JO&l%(IC)w^HOLptg zZ+ohM;PY1E@vvQ~&}Dbiw=B2AL*C`FwA1A9%dl0hCR49HK~v&}nR1oRX<*CZXvxDn z@*$Qn<#CF&nvKRY5m%GJu#o+7${G#3(yu^jv}IqJY8i0Gd5Vqcq-Giq2%*Fcu9kDf z!O|2y#XoA4K&)~X_4Ncck$-5U#AB3*X`a(xssAiun{L~*T6rH)y3pLnM?L&AV>_(I`XB0|b%>Lv_B5O;r7Mh}qd)QnkHF*Dc%6M5~MCFGUJnxP2tRQC;S zQ7-+4+T!c2+}=r%9ik(|5*rEZzlQN3NlT^aBz(%rniZz%p5a(tA*BDZdQRab%5_+f zLSa{)t`$^ihS04%6%+m(T3V zJUvAq#;WJIv9lSbF;J&420Nhn@YAjs_E}lRP0GkzCP|Z+pH_1C`G?@I9xlvrO`I1sAe)03wGBt^B!7BY z@+e*z>m?j!{^H#_xLfaDfnoEaTSoY#uq=^3#-8pxVVU?|?xP*Q99U5vi?vEkiU@f+ zR6IOKYc*SOsf?5n%`c$mG$Uj^22VPz_~(xvZk||)P`?r=n{YBc_5QB@ z5Qh=M2<#nwtahB>(FfPp*Xz4OC{vt}zKpZOIz^V8%Shz2d#CQSJ=OD>z1%KD9LP-c zY_Db0Qd-`qAqPrhkZ#4WRM}OWg~$Fpd^IO2AFH>$2F}%}K7YUG+y^f!5|ztF23>&@ z?RCrcYPP5r?gd00v|m^xr%8^oH2O5TOR~{Ra8-NWMD9Pi1kZoAwO;c2(n9Ut56EP* z=g8|tu-%--u5KAg7C3T_oas~!ys{zhqjOui0BzhA%Fo*5-6N8{3D8oeTTFK7X_GwC z_IKY)7hpyT$f=X0t2Nw)wY(ny1lUouztRSp9yiTc=YuJ4BKJcmDv{3gru%4nuHn5ge9 zJ@PKx6{>=jWokYp`=7u6;)#dyGlLG;gBsxOKw3GjE)DAYUK(psBlmj>foW4aRYxa>GJGUs?}<`MnD#+(2kW-J5iil=NHMOBm#HIPRSFR8h2g4EUv13cq^Hgrv zX{siLqC{3rw3Iz;2koH|^kEz5a+3LRKM0IC%Z%@S@O{k_HUJ|Bxj?<{S$@((P}SJl z`IG;M$v~WuG?}o6o}uW0;<0@1>U(Ue&z_GJ>!~8-WXtwE%@}!M)S&$0|z@L`8zS$!!jz&u~Hea zUj1Y=hQSm|m+mHC@lJtN(raf>)L9sS9NrIHn_50^P5@BYRBbnaY|UFirMx~L*IMvC zof{Y~0b|SHQvT2u1E#}SX2neQ29DPC-kl%dK1s>2+3tHif}A@ zgG>Y@r7rpEO~f8aY*efK*zb=Br)uO1M%(E;02&`U{ms))?|OM67G95(nBEwgP8HL0 z$M=>;23Lb``_?rn>ec;7`ax9`g-lB(oqx-t{7XmxnB;=~Z6Iglon8_qMK&;|FmMsNG_x~n@KA6|GcTC<#mMtQf zO~Zimz{*pTz4{gD=x`SR1b~N3psV^_2N)u2a3r)-H7k7_GcX-=%&P;o3Sj|vn3%VS zEI}u`9xjTSKR8#GCGNb%xb7y=^WwoOEWK{8uE?7BEp7OzAP>{c->+PX9@vG(^d9lK z|CKT00=_96D|)>i8pBMNC&r@V&8bq#O}d;N?=r{0)#%C53X!t#GFbIWz1jp!2VQJb z!5r=;IZvs@cX~|eUtCYdml=?Am$@w{k*0oN5!37+jvceN+;L6zEQ!XGa~A&wProJw z*9$i&GS~Wq|KINe@*?x$`gl&3Wuxmcw|nzPhB3_2hQLdn-(KJDYj||tOagb0q|XWK z0_I<6(-@fE^2!|7RxZHN$f{DE)Gt*a?T=EX8BtV%L!(+z5Z$0(tSofmiRA*mL9z!650cj`XUy*-=?8yXAqP>y1B+5L3-*Um?i?6ZU$ zmByZl&zh+9(VLmHnshc*?8Mj1BzQ4hToA=o1rX)~KK8))6&6<2O)9KcnY|blDG5J0 zFoqFm3pgXW7mUtpjP(72_I#t;J>|G-*yyVXLUH;xuNyjS8*aD3%7(AgIj!jTOdz!-YE#S-y(mGaH=E}n!0C2{S@I3_WNALK zF$?USGF#H5Y@p5=ss%t|71Bb_dI1}853ibj7j?P6BGX;zgr9~U3P4mOS^yP-q?Y*| zKIwrIZmYhHm8`%`t)L4T@)g?4WZu8!aF-x3!3^vmnjd7_-9Np4ci}<*qGxZ=^b{qb zTS=CNYKT$d-$OC|WWR{bPr%(3;Pmy+$!ZgABfQ8-3R;K_wCL&d0RQcIlMpTC0&< zL(NtScxHC#-_yLP+Cpd}4-VjC=dL_B9*^(8?7hwJruLAiV3A@CwDRFoSz5Via*a=> zTrC^Fax0^PbK+-Hpg$d;D<*}V59sonQ|$oj0Ft&riO7nC-ujwq&jj`-(q@IM zH28Z*2FF#Q_)!6I0#^4s+lrx1(1O_+{d%;c01@Kqta?iu#EUv1qY%a&J&G!$xVr_s zWc*lmZW9YPr4Q}2Hv8ic;@x@jMvLDmg-<5}xk=EKn<_DZL6|omUbdGKz59=9a42O>i;w(>Z`J3jdPi|A%Ra%>oaO6$84B_czt1Bqg+2`pu^3D?K>&sz-4v0Y zZHOIMr)~C$D0swjCOB50ClBO7y>`F(LSs|U4X*Cd?X3zAuQt%>3!3&@c6K(dDQ*-% zrQ*iL_~$|gf|Jegh-O0lu&BI@^4ZiTqWTpHoXDXTF0+9*&GVcr8+2n}o{x=A=j4x( zRxWwhhMbPthDI3}DR>T#)>iC8Yfc0QnLpb=^doFhLTJnel^aAsPMz(BGxSvUMULTP z!&R@RxV@92<>;02WijiQx!v0|Pl4d{0e*wfhCDTKB%+rTCD|7vWl34-U7rjpO=@`# zBBo8Jw^2bVq| z3aeOD~e)3d>tYcw{Rb{VLL8_ zLs?U4VG$>MYnuyi?7XIZCaD~B`!#~f($867KhP6?!%B1W80g>V+I&Q4Gb7@qP|5ig)2834si5v#8I;dafK&2t(#* z@yOnCimk!{@p~oe)3bbr)%xQbvmQ1=iEv?mUbvDAg28)by_Vdyz-sjl)q!D_IcTj} z%YyHj;0bADoeW9CVfkIWKB9zIYmY>OGX?Hf0cf9xs;FWph(1Ni8)3u{P+-|t<+iUho04LnyInL75o$6 zlipwGgn(PRSyBZJOnMj_>4^9+80AI)AcvAM6z$l%U!bTYaf|f;A>gIXk&x%$K^G3QMEuf!7T(zjksG;!%al_z&nfW^;A^X zx5)_xrUD&opa_dPslzg4(!Rqrp0pMq5>@z-?MC@J0qCy%s5chlY0kevuM}5z?UfbI z+Z1MlxmS<0M!~<@;lzD=lNBf{ja5N!w5Y@pP3Yu?=PJ~o<;Wp3=3}>iBj5=DGS;(T zbe|Lu*)nb1Q{B!e?lbAMH32|7_K(l$@9g+5cQ4QJBm0uJlgJKpBV6QdqOfD`1*KV0 z(a8Sf1#R*E0`+9qy`!DIA?fdv$YJ~ee}WgrG_1o1hYgX4la5cKAZ}K-R#`H;aQd4# zj}Sge{JKrUk;TEq3BG0*=McjfdZm7mg$#Tkvsm*^#R#@mJiU54>Eh1IgJG{4AN>IiObgcz9VEs|1$i@A+cz@<(Pt3i_4V}1cHf$O6#%*m|cmks?qhilyp0jYvV=+X$V90B& z!`f1-GkB_yvJu91mjdj)HWT1VOTwS*bMzmM^AwAyZi#M*HItz;{0_f>n~YP zDQF{K3=)n>M-pl~|8;qqT$SW67KBw7?SOtB1@0o#QXH`I7)H4;ALmY5*hA2_3Yv^D zd;Z*3g&P4B4Fx^B4a3uxb&Y1W2 zGuUu{wvSy;7Cr5C*gJ4Asd;AD9IQ`8YC(Z*Y(VMrv{4kbKPey}qV@Mp!Y?3oAi(~- z_PPOIOTO@F*SCR6LskWhA4%lhOXvKwHCtx29+G+|I9hARM(=|XC?o==)iGeBW(vTx z-mRpUNhW@~0U23kJknI}_qcAc{rEqDzlie3$(P_fr2`8z3hdi_XjfenHLvn=%C-k* zwV7HJY8F`6bf~6M-FjuRLwlPzANE=!05_Re^0U_85mA2F3!`>}M+gaiFXcLSxy)EAvwz%>(F_x#z)b_n;HS&Dl~vWb9qa_{h33fn-{{o}&3>7eiLeuSHR1N~YO ziYz{n%Y*^&jRD;w;JlGBE(6h$H!iDR|CJUb){0jvB#7xPySsq}Dy6vV8dY~ia(7fW zxEWG*rk+}y_u`NqkLAI)_{_M5mq@!%jmJo+8iX1B-xgl@(_*Mi9kCFHVJnjW^|MKz zxtA#tl^cd^eChGRBqQqpwKgSTFLgK_Jy^1>tk5ocuT#wHexXr$e1~*WYOh7wh^7|n ze#rJnUX6x-*cnqI5)-6b(>_S9bGlm#`;54ya4v3K?|25EKWVg+Gg6NL`D1fA0CKhV&`T$mMi(mzv~7 zL3j)D*6XUsPOSddQOQ}qfAT>pdzBZ#69O%bWT8%O7@&gnJ3G}IvGZ7dVrd3Q?K6rrYp1hI7E?9=-u%`51vQE0O~ z-8h%bZAm(`&emNpQl+_W|3cf3T0dRf*u`D|t4JqPQur5~)qRGaYpMcuxC*fyqCJgDYqf7}EZ}0D9m^2EE?LTUO>(RSd|rheGzsw>ur#bG+qs zhV^YI>S8k9bueCQboW$ycmQe2@Af{3T+v4kX&MFWwG)=bp)a7#MGjQijRvU`A@aT! zEc&RatbtAH4%ri^66!gtavb83_ycv*qc_Csf*xw`xgkph2WJMKskYhJx8xX@n}Sf& z)f`)tx}lwhM}d9J8?{ zvB?F{@~g%DQhV{&ofe25)x=5X)Wk&(FP5Dd*=~*dv?t=XmB=*TV*Lg zLb}~zSl@f518q{oUU(IIb;z0DUH5~8tH#@agbA;G2;%U&Kv>*O{^p}ALx9KTD<{JK z2DOJG@wjUOAJhVeMUr_ktJfNj_#0^f=Hw%zEHU+MZP%x74OItUR8grtQ^rCCn0>r~3}AUq7B&z4leWh-Dr3V%d^?LvmtNXm5ruK!$!% z-WIMeaY=!)VvNO5Bxt*HOX8~fmxJ4<J%PDh!g#gW$r0clwt45U z5ExE$GIL3@gu{aYUDu7AC`m(~?Ozd3C?d{hU#QxkSQHudguM}+Ai@Xcoeija-+1qx zi4A9(b6Xku+-xM>EHO6@eCWCR({|i-uwgM-r3$qGBQUFAL2>h6yv+J|>J^aKh9$%V(TYC-g~mGrhGxcY>0jd$mNvaf+h@Fr0C zeCaqSxmm~@#(|7Qt_?}&GA0gut;<-cT3jrbuQKzP_jz#G3G?p956^4*ahX-~Rl?t~ z#I*E>S`#^rAn;mnc%isJ1~hkI&!sy!o|br5N0#MF4L=XdZscEbzdD8vO6*a{f3V9S z;yF@&U9Y44D)eFV(YIJfb+0y7!pJZSy@KAM24OQS`21Wv(QQAiJ11wOspFk&O+)V} zsU_Olt187yf!M**{9bIOc|j6s7L(V-6E=nKzQGV6NlH5XF%Gb|=fK>C_=A{=ObwMv z=&XQN3mBu@9U6%}uInd=iJY(TI+)q9e?Sjy=O8UmE`<~nHHF1%?@S2hdUH4nIJl6T z-dJLDE>TU~aQjmb(s|UBbGayMqEdgxUl%DX?#*oP@EW2=Hnk2CQYAbkjc*CKL< z7fk4HkqZ&_fMWoFU9^ASt($a0 z3v{db=j}*{q$O-4jHCANN+aE~FThZK_`HzGleXBkdAa$7RbRq6`qL|r;^M9GeHe5F z;>$Wsb5#iG{LO}vf*}awH$YM$>Ek@%!ahrMjDj(DtZn&#zWX#GjT3hQ>*G7Fc-bsu zB@;-}jI3Lrl;r`(NI;xkS_e5VD6J4AtEfcp^x(c!WEXF4UV8ss6KtLT^&fxC47Fr8 zz%V@N=qAL}S#5bZ9Z-3ttohal$A&K9{h7Ebt#EG!@hqA_D(?tg3j)Ww?jj##W~x$x zMv&;W1(N8Ci%~kRl%AL^4;No2&kHzC2nyO?jPGC>YV(eKd&21Zb^YsFh>F?ob|W%U!YW2eAe>S(pRi*JAS%(=5o)8?D&9<`*KWY3 z`yq*XnqiJl&2l+nl7}u#3s)XVn>u<~Xtb{JOX=4i&j}_WZ#A-@I#*<16dzpwjh<71 z-byS*u^=MzA}Bw=bjaJ13CF;-J`$gB;KVWb^!Gr^?6!ij_!-4Klka*U5$T$6$ad;N z#I+Mxs(hsy|(z%&2pQ73I@A(I=IVIx-s)`k!y1eECUDTc?Op zgABYch~fo`A7o|2ZX4CEX~7wvt)LMka(w4LT9gkzX)5tLHYSWkfCD*@srl%QWsL;dO{Zr zl%(y#KAi)2$?mnTA?|7y&0AHEb=Wh$&pUTnGi)DMJ8GTbk?I>=feOZxdo-K*vUF_8 zFp$|xJ%Z6^{eKk&L)W?uACsX|;=}pPSvR9o=5!7Q!)|kpF9O?$QKc{1@Zgbt@T0p_ zkFaCoQIU2y`#CA#qXIlZbaS@DGQwN+;WEbLh(_(#;Ql8%9r!%4d@txtIyt|h!APy+ zZmDBNh5ujf;*9lF$QIoForK(=ksLV_>gIc=UMfu#66!6*Ubb-yShs;V7ODmbSWO6D z<;V-hi5$H+gRoD7)G?-twJY*Q;T&pf_LihoKv0xL|L_) zh8l@btSXF--h7=(AqBTP@=vI81_p;YtB_NoX%{Y*-5Z4>$l;U?i|}t`%8L(UW}E1+ zkjP~r)5)_0NKzxdOii6 z&4NT$dyS%MROB45#Ic7LOwKC@k_+pK0gghcuGR$Q-TLHMQ&`q<92{EyUy?+NM%pX$ zjG)62c>JIudYQ6|udt!6l$kY^uqgZH6$9@FDm;>$o6hj?i zB=$iF46LVzJP~gA1Ts*8D{DdgsQIW;M?#Q*7-Z1-Asyj=jOxf8w9gByVW~$SI21onOSf@Oo_KUZ-kU; zP9Df7;yXQ^3}f>HyAz%mkjfd3niufX=YQdGE6y6$e!e+hJh%GJFC#v&_7l;^Xu@6h z<9fxJPDXB)FFOU)cAnw!&SMr+aSqhQ1QSk1kdoMTCxXH%Ti*KTYtOH#rE$i^k1&2> z{kuPMK)4>z($yn7zxKzt^4dA|*G%ksBHf#`Vuqn^0me!e+Cxi}CogSA2+|W4nmnpX zA(*%7$|g0-*3HD@*XAImp^9hv>sTa01vCZRo@`JlnXxjtFN(-Vru)ui5dn_#1{NRo|Vc>I!(o!VRX+Hibug~vKi($^0hvndN4W1B4}N|GQZ1f zHDr^xPgx#myLXwR1U$5?#aMbgyAuVQ-wsi_i=EXsVGs3zXi+BLfOH}Dy3E=ArSOS5 z&bqCVN(yTjn{j2!d0-go&&)Ho|39z4ZHB$j;8&X^;{+fTigSBQz|mQyg>*YLCwSq> z^RGQaU0ZGn#1vw>n*h(j;rR{QE)TbPbe~+BB;UTFBsS;I66VG%A@w#C-c+d#OFrY6 zzshfN7jR*lZYqw`j~Hx!iN_!Uk)1;hNh*ZmMk*Z1SSLesga)q1W6U`<4t8&0Xj@U` z(7FIf&@6olAHMcul}ATL(tp-S#FBAkV}$C)$7?ioE=2)qBq`>s2x~uHbOe@#0T*JkSu>zIy zqLj+h$B6xs34uH*E1ePLKKEX%B8x%8e1Al>$q7W|K3Lef4<@yKv5YQF9FJgv^f?#C z;-!h=HcJes)0&%o7zj!$GpRsm;t2nSQ_5)Fn`rvXuV^7#0vA=*6QvV^pqg2L( zs)NcmomlZflVOG+>@&(GU(Ni>it2SwmajPZ+y9~=uIA_76GfrrW)jb6U`r?#mK`#{ zKbBNX3WmhG&Uy}=m70;r$Kav8KMzQprpMvt^1aZ0u{Isn@a=`4V0?Jw=?kmbNHO-b zJm3QjWDdjkE?o^FR9_hDLWY5l++P#$WCH)7UkaLF5Q2v@jl;cRwROu@+odCx09sfhYCJbysuTHa2C7fnFO5-uXqMz@|vOL{E|3LOgH&4!Z}MAtUdaaNbE<7)Sy@(r?M)qHjeYT#awHw?#fl-qUfm4-o z6ik{Jf{IO$@3oW*L1Ch_UC#HqZKmO9d3zJJf&y^_tltF1ORmgJ_6$H4IODOxt|+Dg zz()hl5|e#oVr7AHNJM{DA+g{HUmCP>u8Q!_f2sFPmyrrT)OqJZcO?*J?xOSN$Y%%h z8N3x1CK#!%!tKihN7{X& z`hc=~5eQ}&D41hv*Hh}BcW!I>11fe4WZMwUzNo`n!iYaH!9^6yX-Q-)O+nWX2q{|s znPH?-FJ8m#y?QM?`>wi?Xxk6q{%5EIcZM|0*+e)^j5dA(y8lZL5w?x*0Mbs7@U3~{ zz3{w`k^U;v*mw9hP?iulqhTct^@`|!$u@b&E)MzhBRxihpq2of%YTwWBE&IL$c|l? z>N1ux8o+U^Z_pEm%8BOk6WI}s>S+N4EO&I`x*#618-o;HQ|a&=ZmdyZ)bh^abKzA6 z#_}kipOVMtN}35>(Y-sjRB$Kt+zjvY+45n%-QW-xFjV3~o7b>OSxB2A)3lL8-AWDU z&x#m~<-o)aw?g6FL;*`k;X+8Lgd|W=sqJE);0bheY?$NfPaSpY1r0W`*;>32)Qf_qA2)SHz3HDZ&I7sO!~i% z=F%*^d=c+~r;dIZy^~Z4DHgT-F7rlMlp+L~H+GQgVjsLRhTJoBtY)0Q{L$ptPwQzO}0N!M2 ziL(^^qVH7SKTpFBy+@ z4>FdV%9Au~aS}Hd$>g4L4WP zlB%}H>pTk6>Q*u(zbf=L`5kTt(q?2%e{t@sD(WZ^W)8`if;!%S%Io50H_^>M8g76g zFBthB1H&~4RFZ>FJ#=D7Axq3Y_yOcAjBwe7Jg&VmMq2{O1$wYItY-&<@VFq%zbs&0 zOw~Vt@L6Djz>ZDJFD!zKJIHd==ZERLkw3q-fx0I4QJ8um`>End=3v?=@VR0^Vx^mE zu~;#XaS4-H6O9%ljWtqkH<{X-=@^y4vpCyG-uQ%hOmnvyAfA;c7dLEsQ*C$NUwg{= zx9e!rbz@z!Iu&f04{ByV1(naL{y-5)rZiM?=LWZ`KZ z6o2FG*%LhcyOFD9l8&9_*xY1Hc$=(Y_watRrB3tH=-QSQ0%EpSpPAJSIZ64wEL&n9 ztZ5ym@1<)44}BqJzXjL#sPwI(_zH5!kmO40X(vhc(2jTE#c8ad4j7_!mp7+zJ`V0~ zx8pgT!iX3qlzJGLrg0IM5S#ekW*uohXo5J2)7V`j0~0V(b?iS%qxz1pyO`$_MV@co zNYwM!vTn9d?`5_UiffWm=k~{+n&u`rks+(4t1Vwc2@Vx)suCvZ_z6DG4LO7Q|W>922=bi43ERKmi{9BJo9uoy~BNvB2cCRyw6EJ-prFE{)VfY z!6Tslr#P4kxgf82`>YTC#q9PA4*@$G^ZUMdmK1B?*(ld@>gb3Kq+UcZTZj2Yg>T%{Q~0gv5*zo@qqP){z6EiOSFs!7M0m+Id3;fX zaiuKwvo9n*S<>X|zsctUZ;d!Raddx2ofk$U3hGhnKfXx*X9*&6uBs9p`|j+rGC5sp z<1CYvCajM{&xG3Xx^Or!L?>|KHQM`S<*`?y1N}bbdi0_K z#imn7W<#--r*@H`WXnpM)?b%xkw_$5uTr`Nx0F{pxw<4Vp9`9+t6$$+AC;0C?FbrV z@}M(SsC4W*bKRmArsh5;!8fX|HLQ+6A%8Gni_`lC`U@5nMYJm=6{c117-FraL5~?X zy_+xc1wOy?VocUiM=#f=R&ynv#Vm4~-Gq4CJRoLSsih45`8y{kUA8C$L~>jd?HxHJ zv~4Mxi%?1V8yQ1C4M|L@-~@Lj61RRHKnR4ZJrZp@k?3>WMMnkU$<@6rzgev#$XVCFt)VKu!-M`c z%PPCOy2nGz0XN}tPN`K~%)Nt(1LzeE)&r_yt_KzJsm-P-##HY#;9E`U7dCV*3@6|( zGIze-_u2qNUWOWyp~N6+(D#2ghFM zah`0W453yQh1o&amFmLm=b~7}X#5oadid8hyQI*N4%hm^B}~ZHr35hc7!CxLcT}P| zJs``meInKPXb(Wy*uhH$KnSqQF%D>44ndm*ill&3CLv-7LXdLjB7RKoWi9DGfY=4T zmN|nkbRLf=yybz$y`yZ_#T7V~kKw87O@c@$CN^xvkOY;T=$Lu^RpDVcPEzp~$y?-c z+hGD}Dh9ZTN?h>GdQW^1ArX1d8h&ePz@_O6z&x-#_TjwoL}u2x80*NDQRF!VqPLT6Bn3c0r=T=WXN7VJC{ZY!+C8BOpROZARGoJes+GbzC2Dbcbyhl_a zjUGRq`d0&2=Vp-?b@I=n!#ei7Hl`;Q6 z%wq$fPc#C5QvnYzShJ4d-SO3&D8Vd73l@26!BA`;=%t_M%SYn z3&}ba!Bn3Ad}3tETcH6{UmW+=*7c_}BVST?8!(!5D{`Vx_8CZ0mI`5AK1pQC>faSrEp@ZwiY>t~|g1iie&P&uNKT zas^DGmakyzx0IP;CT=fF7GeZwY~o7u?PV*F6{M`u_i`NBzE`HPZ7FW7yR+6+hm#{? zee0bpi2glJnt(=yI&Gl^o?<-Qy~pjA0YchrsHlE`VQQO2TWK^u6e<0;PaD$n(7uO9 z`(35GUDRI;!wJmU2Ig5oN1~R3g2&UHPhw1CduOkQ1xY&H{gd{jRs$b0k$rz28$01c zxKG1i`WMddKRBl3b|?+@?EF)yK>s&zMRbUv53r3lN2_LFLMf(w@& z?x4OKIQ*OUxFpr}uUGH6P-U{&J+4x!DF~0f+5p5kU``OMXdAQNP3-)@IbfI|AVU@| z)Zzs=(G+vy5%-Kr%Wl={C7VYqM1D-N^QfO&MEVv<~ z*mLBPwU!EcPc_ulAD$@qP;&5wjO+(i44IQ|p3rYu6y4;&JW!V;=upMjg`&|CqQMxq>ciRSL(%@CNHxG70UFc$Z_2o zk4tJyf&S^kQL8qzvO27+!O%#`?+w)!r68T=8K1*F-NAc+0jK03}_b`0v(P*u`~$<(D#IHjaAZ>OeNRmlS!Mq%#@)7#>diQ2~9g{ z4p~E|uPUnMM~n0Pe%treUdrLA+A(}n+3&ezERi?uK%a0}GCBZJK(4>hKMwSBD;?HS z<BBi0q`b3xrz3?MBnIICfvw3;urf8CSPo=gGeHh~&X^?-z zaKHFXL4$BGNWsKLaTr7t9|}{4_;jl1u_IZ+y;rYT^)y7)gR?ydDLAC#ukdZjlMPHt zXzB80jgmlTmVVG{eFK4}WKU$R+sgymD++hSe>R4btp8ISoX1s*JWblWFhR5>EhF|I zo%&rmbLG-qqigW&#Q5V)zRMIVKG?q(Jbm(_cWQRf9GKq-Qggeia{&*zx^0-J9xx0F zTn6+XA5dJ+h{53*0JK)cU2$6lSzi{fI9Yo_i~)JeNXBO&gWKB=`ESt&rKSmGwjdt>tx4k=4FA zYT@5M$|7?a{g{3x1li+t`ayxplmUy2jZJQG&*d&CB1>i)4@?SS8SqATRc@Ns3T(wv z&46xgGF2{?Fz4XuD{=a6qU*RWjXxCdcG9F-CH4H@IB8ahTSuo<(0T|g!2WC@mX$!3 z(rA^hocP!hq(|s=Pr`<=*%X9-V>bo9DhV?21sJ=0DzlEF|G7j0eI321-=^7lTP&}2gk+{GtVXmSozE5#U^lQ&mwXwgF zjmht{ILjK#;mogMhlln+4?#mCpJhS+bpSEY4V30fk=u+l^yod}Vs4ofKvR?J>p1Hi zg~hp64s-HI2j5unm!MP&4S&&d+Q#1 z1?8|-ro`qh=@lHP$XxyhQX;GTbFB3zGQT^t6NQ?5s2vg@544}9TF<7R^h}ejNt33L zw6XaqH!cO!oSCQ~3q@m->3YTE4I4(%nAN_vJrrxjI?}Xw`6qWSQAZIn)Ug}|Fh}Ca zD!G{4C~F;Y2jb*~WfFWT*-DlxvCgEd12>2)C+8(5rQ;Sy5>2LLqa2J%w{clSWXPZ` zg*FVEQOaxpmqB#*X~-O5jK#?j)hC`KZ6mcA>Gr~_f938=LM3~Zzn#! zjvvjW)kdRLoT(ow#sdq~d_*+=u|v-THSLVH=*gmh4^U&bXTZO!E8oh3ep zmJ{tT;agSk(BOR$r&g(pMNfvOrY;DuY&~a38~h+ucY(zOS&aJ;x_w+E?KiEP&4KDNoD|ehQ{55Wd zyIsJ>O)3~j%1wx3GnFm)WiDoSKkDVgY1_9X!82-9fV%FR%jXJJFwH(Fs zcWCGND1#KdTmY=~v#dNNi*0^OM##Ik3Q`{TmqUtV885c>9iH-|rafa;Zi63SE~K); zQZAqHuS45Dc4}TytHzIv24lgo`EK?jajUV7Z>S814IUm_S~!6s|5JkfV9M*O9#nX{sK_*2+fXvcWB z`bS-+plq+QL-e!@8sUDHLG3)I;MIDxnXAxE8L)01cG$W@mFJ-H5WCh8)TRy&8NYX2 zf?%?`Mh^6?6<@U@eI?;5XMz+25prVh>|g`hJDhR>M&@-%eqxX&i3n*z0oB@KSnhh7 zmOrJ}j6P~AOS7*{ObGgPRPZ-HPq*(OHz>o?COxnx>f8JHx=vNUkqad-3)Q1T7fJ!J z`ao`*sr@elC(V}p)cy9~Sl!K#bC;wI>Xr` z8(Vwfa}ZpCLk!ouy|Xa#q1Q%F{N8vT&5LIrCmOoa1|gr^+8d{1Hn*BiO$SGk+B8iT z|K#X0FRw2&_2smiGvicJKh-33L4C6Xid+oX5@SR#3JA-A5;joLDYO+C%>C_BWpoI2VRpsAicE0GI5Kn z*8+nnHhDQ@bbQ$N6g=ZkRB3vX%EWMj@2E0p8{~onz`ODyfeeMf0f15E;o~~n45ZTI z7h<7_7y~xo!gQPd=!}r*S!X5L4sz#Xw_rm=&8}d+IMfW%Z%QSuPMgJjAaa~Q*v<9l zq7wLUQfThkc9dOHX!JSv*QQ3(seu*xr!)&cMI^)1DTEzv#CSM1*-C*<-%E#lT{#c{ zVt_$Dwgw0$vPG7rC{+DsMn?Lq(^Uti!MHk6IhyST9l{>vju={a1wsrq8HxNz;}O%? z8#O3Ns*LGWjKR_~w$UE*dhv6ea4$I)=C8 zfwc0BoyC{e{2|U*E+_9q_U}w+o(*=V4ZCzm;C2WpapbGB`}Un2mlbFjI1e*XlQzb9 z>VtYA*$yZ_sI_{u&drP5beZFRHG>-C>#>axzeX|~))n5x8XK&mtDSaI(%RZwh-5`q zwY!i@yF`ag}VecL7w;_AtAK*YL5pe4E=Y$eH-Jt zcdlF7eHBxk6=Z6LH|{b2{KN@k=}y=m5e~kIhes=@jvd#bT4mC@LcmWBZ%?k1BsFgG zF{gP6T_r*P)Qj+|#QEFtk7xL|54}@``joHV$CyzdUK>0%Ma}6~ZaH3vot1kc+P4n# zS8j_9W>4yu?|KZ#nqSRv^VYdUihBtoH`!PXgAy{wVV{*GBlJu`BYJc#e2N#r+T~0S zsGBF}X>G9^)>85ZlN?~ky_xg+gqmVlMo_S`uHN5Cu==#dm@F$kQkBGwCuvV9z_8;@ zA`MsSI&+!AR$hPc zu}AH70n3Vh0ObEzQx%kv?I<2U(Z+^v-5npC{*w`_p)jGG(D!FQQns(sQkCJy7WJ}D znPkfP^QY8P`P#oV=8EagAX!X&)`&0daCcg&I`M|Uu`fJYN->OJh z`0wx%zeIvwH`B6b&8C6mE{-e?tjoOd(iNa^kbYN_OS!K!enN$BtG)xCUj^HF;>&HL z^jHlBB!%dH)~pJxgX-{|?p+@wgZlSF=l@|h4nti)kt!fj8l|0(2igkV4}A&>1a5a# zoFXN-%L8(1dWOl=4p`Q)v)Xi8(5A>F4S55NVNrRzYl8;jZ4D6PFMn0sxPMMBTDAq; zuX0A(#ott)9c+(xPYgC@X~)3kx|Cv1rG}v&?lf`F+`o(;Om`E_3JSD;AqC2Zh3;XM zBLc-6=ig{5?EwWaM(f-v)P~px762Mx&d+$I`&e~K79R3-Nx}nkrJXq}0{%PPNPZ6O z@t)O8`Y+`(py^y3QH}9@Z~LY`t@sAG==$Cvd`paWOFqKm89!}_r>EW?b)$EmI^Lyv zRDM@;sSXbP3Gzw>^UEk<%O(tVCG)MfFuMgfg01Br$J@uiUq4$>2fbq-@IHDmnCsu& z=(w9|;COh&+dtNwoP)C;6cD2i;Yd_pM7B0DxE(F${bio3AP@{=>*kC`|rNj04P^i}Bt|Rpc69 zzHxeV#3)x%aVQ;x$3@wPc>wA2O|9pGGD;fbc^1&5e-85JYhrs_Ux2;*N&|6$NQf$S zNl;Ww359Rza&tu$T=k=?7y)M-}%?WwK`y>K~z?IWw5qIWRo;D zT9{97mRxsfJs7Vui$8#1xlnfW;H9FUZ>y*RX<85V@B7Jj76|1;O-*$6DslC}haJK@ zt^(|qQnxUyt(@SuY^0_vS3*#%l0x_S;_M>}vsb7KZYUSE$J zFd%)WOtpl)?O0LBB;lY363+}I%!XjdMM7I403RD(O&*|`5{06Gn7Xh_^NNV{TC3SwKOS*Va?aeT?L}b)VHxRPy<$!EsK;gE|oK> zO5ulP77iGJjs)|XyL6_@%C&B0;+hPn*M_ljaVT6*w-i zSfWGWYJr|i^sV{TI@I-K#B{}<1L~hAzBIEt;yhE2J(w2aZx&~r_;NhZETihtQ2Ly&K5)g?BBfD zSl-?+%|{p5BqTw-C{vC;BZiXFj)5^%oWMvH3Y+G#%>1G8+R&6JmR!*~Y6B@>L|b@M1+?L-VD`S1Cu%>SQ8!Vu65wXTFEWP!l^_ zMxOvorM>j#?Q}T0?$C8rC!SPG9-s#KgsPy`;D%3a+0xu2TDss}2Dm?l6!jH0*KKc32(iQ7Q*6+mi?hsKk=WARdGZbxUCJwv=b=5ou#Q48rdznNZvI6lA1g|v- zX0C)W1i3&&{VTOR=Z(;g_Q0wJQh;VdYAe7BW^^8&Bew#JyG&6ze;?KUtHSFb1BD{K z7*_8HJ)rm<6iXT3q~9k}xx`rijZkD7XTT0svXaaq_`XA6ayDTTKrBq(%H|;Sk_-_e zMN6-qNXUmeDv(I#Iv1!BfR_cNw94qF%XX@XGw#5%Ojgg!cBz2P#5?>L<5{4#GMQE%ypV3w!?@-)pD}~u^fat zMVEV)l1F}6%@KxnKp$)r-yLc-!n#y6i%%F$Bx{$0`L2&(Idf>fdP`CWWaX7FJwmWi zWoduHbU^L7dv3b1=y+~kdTW6o?O0ZHXPN{}&KFItHteroB4bP?FfS3U*s{uQ4)QG6 zn)0M}M7lLk9@7zxZc?>+t314!yDnK5*W7iO5h_Maftvi+Tb6|Z80VHL-1mMmGO2BM z9NHfWrx^XW6B2jlxZupHTiBS3vK^x`^oQ-qYJwZ0asB)!+sTm)7&hJV>(N0H_THKC zFwRs(_X<-G;jy-`XQtzbtSa2XPy7?__dF2G`SgL`o*QWnhEHx3{Nd3~mU4LAtl-E4 z#x?c0G=h_k5vn#}2p@d8I4Mirl#rRKQNCtQ62GGPYvW-FQzZ1XVea1^w+ztqBkk9@ zlTm0A1iQPOuHI~Dr%&1rS5(mF5^XhVq)|#mwYGq*DpEeQb-b$e*^>l`lC)c==pKEDAsSLmACmj=J)Z$OSVG6Hpx|fc zYbhs{LG_%&I2%tsA6832H%Cq9}Xri0qjVxp)p#kWt1$9+!#f$0+iiihUe$j)!yAH3;X}c+ghccIJ z9zFxUP%Yo(dnd>eI(n;u5Ed?xsT^MYe~#xw@<{kI*pXBqeRT`VMGT`8B+dLS0WEJp z2?_&75ls@mzYMGyY8f(TWn}~&#u|aKg6-i=u{>KVrXL*f%`2A zQ-Axul;@iD#|_TS8U1piasB@4S3@XXTC8}sssFWoaFAlezt{IyOQqK18sFeVG4XRk zOKIx}Y0dn**EgF@iMRp&5F)rZ(*xP4rpcy?5_0|FUmO3xa_~XMkspL9Bp`dTO6e4_ zEE=rwa51|;nlB_6V*6rK$ZWc*q`Soox2br4AAf^~i?v<|<=^#_DmYes6t#ydoWyHo>AbIHL zCJUY6ZPUDg0x9cd&5zRg)_-Q=>*$3Lr7=G{aNmq~I_n2F==q6iJ{2t(ET}{cR z=gWQ}RiaRbf8j*1YU`Zel7%JVDwm5g%l!-zJV8PXqN2idwdElTD@9$VNGY95tFo5a z+QFQsJl%YDIrp23ynjgmR`ONa6DS`7PgS#QLd5l$Q4oMosyO<^Z5+VT{$E$!o=+KT zp&VqkEKPtEJrwGt?YY`TEB+!>; z$C*Ul4k7ZG_-{rCQyb~v?l&$>{W#483f)EUnl;-4>gp8e);GK^+E+c0iP-}e@eQ1Z z%smPJ6~Nk2mWl_dRu~%R%Z+5L0j$~;N2-};`%kvRoULZXGN3KVI(Kk zg76ln%kK+Aw;=BZ1R1o0gl~f~Ywp|Nayji3)gLkgq4-Q_eTd7foeulG5e*cO>UEFd z_ypEo4s4bT0S<0sIMKPI9a)KMdY8DZf}9GJm+dAT{~*;QyG0N{=Xdh~Dl`>44&2D> z+u_Y_@K)XLN4F@|GRW^c=)7J{TwVPY3=MVeJ1LG+h%4EbQL~evh?BsvKLmc;nd3~7zD_6BzsonTN zu)w`r=-w(kD`2ZI+74I$=(S204E!ach(N(BTDR--E`1SdSxRz=&ucMjZYK0MXfC6$ z*6Mt;88H){^>E1fu<8ey54viq$#bbP&_y|st)v;Nt0FdJZeZNDKs2|#Rc#&M5R3JN zB$j_rQFugeY+z+VN^_8=H;W~+I-kjh} zE4RO7VM8nNKBMqlRkJKL`)G9vOULT~Rr3w|eI@92WXTjT7z777AD5FU}{GZLBV z0PQLp2DzN@vlNYC3^Sd<)25rrIyj@p6XM9M?x}rFy&Di^3rBPLRh3`jno)}K!{3uj z1XtJ7=@{j_f;Gk$6ro6+XT`r(p0mRabCmUHt9(5fZs8*8i}KkY)N+2(?#0))u^@+Z z%&;T*GmrD{u>^!(VTmbOh~c!zov!0FjXxN%wUMzL;7BX_$C6~|0)$gTbeOABQju>e zQjCnY#}|$15;*}CVj0qAkzg}yixX^5&_{>}c z;=9FMr-fB+B-K)>#0Azh-%o`)O-Feloy>^dG7^i^!3Qk>*t^{D!_L>&D{O)d5q(i9 z|3!ze;)e|*Y0KR6%GgB)6jKF9&Q%jTs33+hf5+36no0}-09RgrQ2qAj<6}8RhiXE{ z(&i8PwFO0FGvGo-w`!}w!y}cAm!5&GEn3wmpo~bNsUL1 zOmR@uN{%n|v>&N08_!l>4$@atc!jWgoZfui3aj&W%@1Ux-xCY0w);k^pVXqtwmx;* zq;*vak8De+S)KJHZcx4zMP(!04^ts2mjdKR(Ag38bp4=3Q9LW9=&Bpa@x87GbdfY*OUqx1>`-2Y z=VG24NN{+IG13LngQ#jUNPNh*NZ#4gzKDRXHbH+sjdaNs>JtoS(i9~ma z)Tkjjnz$2+Jg5LU0x5#Cf?&awXft#8vmoxBClF7iBY~7DSifR6(yVUXDxjRqp(RjC zBv<|y{evi=&ag9q1o`uYwIt=OaH|`M9g%e92}3s+-qVozpjVt4<|s>5_5Y<`XCT_6 zAh|K@`HknkZBe~~qh%0YYUt&P-zTXzEeFhJZzUkeU{TbYuI*IB0=@K?z2(?03a1kL!-z~zIpYYU`d}P{P4xn+COSrDveS6kR zvy{_586({2=}b0A%E+Yla&(5;>Uj?6iu&wx3z8h6@K6~gqD@&|`sM5T+;9%OcA?lV zmU7-s?7kNvXmZqqJz34-7F>h(tQXKX_^n4sRF&VTSVit^*X9xDSw7^#4BM+S~{mYz(?K~9LnHQfa)y!H+T zfq`^c*6K=5Tjnu}H~P@6%~mRvi53uhy{2hxNh2yKAd&mli-ysmY1+vL;Q50Uyue~j zo>uu|AoJ_i&Q`MjF1YcUG`YjP5pp%O2lU?2*%SZTydZOZ=@0ic_A2U$nT(9NlC1Lw zYef#Mn9vjF7WcyZb9Bh73Tl7+|a7A-sRF336If6V;FQ*3UY#aPTCR$jf~Gfo_Pv5D&fvn7ur$%@rzNSk*xf^?tl!2 zgD`4fVq)=&3PM zD%F-n>amD8-Bl=>{a?$bv3L?}Ao6HEd2+Oq4?^GH`^Ys?9yf{N-$qoHA2Bh^iKE8G ze16_uP`ssO(lz9GLOs;ij*s6?eB7Y)^ATl&-bn0aV3Rt;e`04%{>Z3> z4t;4^9bFaPl#G;HRX!X^kS7LS$kcztRS_VF5}pM^3Dr_I1N`+A9y8dWdfH5keTpUv zj16M}2NPNJ=rir-!C6Tn2ojLoBVQ%tmoAtaT$54rFp1MVShfU^^XDivOUOdQ(h5^% zEJCP$-@0t||71qB8-~5a%wtiq7|<8KdM>{?a;NWWx0yH2*ES#HY@hK zpq3a&iRDTS%|#dvC2}IsG=d%{VFxS$#APvjE(W|W$~1Ju#kOe3Pf-0zT|5e_O-|WP zL z*k%+=QljgpU(nPVXr3x5QZB*&MDVdbjMQwAH?=%{H$qO%O(t3 z<}dH$cxN#xpbj!z!J_1sI{A;@tCE6tDz!(o^2LgltsM+cWT26-0mQdp3=gstWh~oH z>iJY`FqBI2lzH>Wr_NLm6%yrT&PqZO(?XD<={M6wIosc2l)2r|?8k2vNvxGcBFS9~ zhbmy`FrZj4< zaz)cSXy`0>#vQm_U!seH1fy1?w}wshOn02EWYdm!mS7m#O7`XHcON$s?U(^&E)glL zx1?}_Qt>M(`8tVP+uCJ`WpSj3qiy`oYKNoA9&5;0Ra%XbwF1X{TxY6BTd$2MA3TjSAY+1tf})`#$7ZY*k&P1Ev#QulV!V5 zh}0x6*o4tQR9xqb>D_=6nS(v4JphGu?sA>4dtcw>^ZxA>&rUQD@d4vW(>4uNd9qwTWO|-a2z^?ApU>ZW5R=942Q?ACT|azZX9a`nLP3#g_D5TXO)*xhPjC8JESPl zfpA7&ztVr$_mj?df!8>s7#d>#(gSJOlH7awHw943?czgzyN%*agS9+HrKr-X#Ysza zeA&V@&3*!WS=(=$Xd3mPa662_xbiEf=HT2XDuJCg1l zLM*2AU#>;5>fV?q#on4>%X@q=ft5^CY7d&F>p5_Vt)%zLNj0S}X0^M&Og?yL+fW15 zBvEYH?K`HPQWPr?fTMdk9ApUD)tQ9TE?$S0HR>Dp7F@PQK_fZV>HvnSJJ(M`v8q8wU^>S)dLkx0LJDcN8<7U^-6QowSzy;q@C#`< z8NVE_ruMulrxPh%zmx?-dZrX{x!7YN|BQJm*%}sI(w*lHa3EGFbr;pDaPM%1 zA?|p@wS4TjCaJ{`wRrR1^9S%a1y}{9IRQc^3?mf8?%P9p{Y`YB01EQ`WBql^g(7U~ z?u>h%h2Kwxv`Kr1q}M@n#JAnlV(qHP5txgMOk+=R8tV;JZ`KpK%&ATKM>25x>O3x8 zE8ixW4U3@H7nWVFZrCI1;NUr_SLdu+R-p{aWc8z@Ne!P=vx4Z_dYixkUkQ|nfeHaL zp~4D-GSLdG1v_hwfBTCm33P@e)S_LeT@}=UYuQMm@BrklW;8s}Hn8JnVn5ZLU=Baj_(?KlGqk*Ia&+2=YCc9P(`K_pRl*jGx zS^U&PJG3kAWUeLyx6-d0N7XtQL%IlG{2)-M)k(lB4nklU3fEU)9dglmLsK{>>5qpUY}+6g^VysZd+i&YNBH|!Hhpw0;0m-t{D_)Dy zAfU3>s=}goNJIPd2oY*>%3aZdh4bR7RSal?V`pmK(XI&x%nk8yHNGLf9EdL$5Q(8UQC&r|01q9J6eR!9*u_ zsX5L+YKY-2v#u^e)F|^O`}KO4ImuCIqVeOhyx;M0)dX>|{E3Pf#u4H z#7ojv%7`FvI7Se<5ID4kfoR!6Xcqm{TU&>SFOnp7sLit0Xe|_?9r#kwf342#}tJIl}9atvUVe`H@mz;Il;cJNJ^hN z>rnCeY{Ta&vzu*!UL09Y9h*oLYXWfUJ!h81>g(g@O@Ec@MU{|Y`|!WCl-@*#A>{?7 zikBWiu`vOm7kVwL*FSp1&Rl9fV@k9dZqsw)RxLl5j0S^pPtd>H$9PBsfpWXHllP-? zNiccKN|u94soA_o%d#5MJTE>7S97NAD09AB59m^s);9_r@{|0mUe=3KQ$_RANCPc- zXeyUhz;R(Bo__SERXeTG#?pUD7J{W(a(q6H!hiXq@R+W7?N@RU!*VxhfC?*$?$CF` z7~6LGq*p|G@1U`Pp98qjvT1^JPzU~UJF6a)6qqzI(-Ud2dxyetFcr0nPB2h;?Yz)Mp^ywW28_40tm$see$z5 zZ}Dh;NKGGpd%Qi#HaT4NE%$fNECzm9Y&tJ7n>)Gl^ixFWuFcc=;dJP}Wc zDxM&bN(^14MG1XP_t#XyQ1GCvuGJvSDny|&epGu2cn&YANYr_JP`S;zFXi|ctMFKV za7x#_aT;n7Vtr(c%02oFbE#1_HV6z$5l)uVbl$D=NZ2%#ESP9Qn@tTB9vBtu#o;ya zD8sna(BqAbm84|}N$5kc(a7R)r*f8-?lYZEH|_7_tTley!8tbnRzbhDmHM+)RbeyY zO_mA0u5awM&V~14H-CY^6rk4@gwZ^W;$AedwfPv<^~>5<5LeBUOpX;~_&xY&zs4Pq z>V7BURDVctJy?U7LA2VJ)C$-^?2)0e0gRLg+*N^Ym$``4&Qc%U>_qu`mC2($!t2?2 z>K}Np)OY>Bu47R!>qgP6Ps7WU9YI-wV&W3ZApsUx-%(%IA-;MSO-R{!eoou?HnOQD zXr&qD8P0-h6p0{o#^G<$ne~r=ldGV`5@@AuVjT7-Y0(V1+|5 zGIp|}OIW4|SD>3lbFB5lF9FCIQwuf^7Rqrgq=~bO^4n<$6XE`U2bXsdCc+61_D|;P z(S)i%=q~7wH0J7-#d*zggY!=Sm^hP@m2ls>9EW0v-`k7$`VDstZbovvI?@h6@`y9L zXFQj&byb{rvmY`A|9OtHmDc^Gb3Wi_*>wr~ZE?K0>|ivGB9n?ll0l1BnTSYG$bwB+ zMTt}%+@T3$fhV#(Dcu>&G^7~Kif3yeO; zk^QyOB?t>)??((t(fiesT?^qjLIL$wq6v@3m@{pDL_HxM zpr&Y@I>xey)eJ~af3=B`wGvv^v~iiR$E;CDx1llg(Rj{aU!72sN2e@Y-$2rc6q<1D zkHWSN%H_?d7Q!FwP)>>{H@)_fOBBoD5g%{l1n8x|iwbcQvv?CgHs4&mRTFxB{EXH# zzvOzJ5uqxX7Ng7IXnvl!337d@WblI5a>Uw4RaW{^?acs!|oM+R|(qgLS|IHYS@|21f0lCMp} z`-eT1W(~8E1#W4FL?6)LCXx3wHQMI!9yrf8I_KF3+XWQM%Aq&Vv^Y-nL=n%WXQ{A@ z*cT5qa&{IpFJ66m?0Jlog42OL+!8a5{yOh z&bqd(_N7-o*oJl*43n%K@1XKw5W2LFyicb0t7$w09XbYP=Jh zOlEa1Mg>XoPhq#G=X?ruewg?sVdU|Gp2 zLO|lur9LcY$6^;_LM(re^YuIa3b(^|dzU(lu5t6wT1?V* zI-VV7EK+lf6>x^iy9L22E>mN$1c`;e_G$SA7Ya2}(}1_zl?|y2iyiI8i+Ee;#qVYq zF|cd7G(jQr@YJ#hl}RbdN-+KXR?#r6fl|&A+T2~Fz`9ng>x;1@<~6}>2zP{vuKnn$ zBXKJ-$mW6Pd6zgf>mlT3>4A8APEniv{9nI~`goSDsd=pUz*0`+p(EK*+Mb^#ewojS z4WANu4ii=0CnAm#70$-xot#k?9_1iTgVMU9X%r`eO!E7Au*W>M^0;jv$R~kZuX2KMqXFi1LVJ z-F12+L2CREoD$%`pk457d3aEJ;dm~ph(HLn_UeNEnvEOZem64$Y5)LdssRa{J1OgB zCriL`&K7Vs5T6par+{eSq^aUZ}MZ7q-2hh&9k3L+_=P zlzQFX>=o|t!M;xFiQHVpnlOf@BaRe%GiGY3_Ua-xCSMj4~;J~WVmv>ZT3iXQ0~gh_c<;()!>7)k=aQRKm8 z^U2^4B*K1-^=&RUQsMy{Asv{;mcS(uVQexn+`7E}R?r9`xtP6(Xf|zuRRS#9N4dii zRy!M!9o*@L3r@vxXP#ZX)yR@+TZsMIY3yFef!04p3R@!B~5mLWVRB+*er~%1;6=Ytk>t=H<-6wSsxW8a}d=y5k|NRm#PE5 zkdRCrlWPyL*SoL7okuR)n=h9Jn)KfIj+`7hboA?w4$kHdZoQA39PZkBvXQL}>lMvn z2XSZeaeFlVvnOT8Xn#Zb@Y5S08?LOIn9NHVvnCl0bwf__?t4v=9Xe?Mp*5fe)3)L# z901AebI$%X%@LlNZAw1EX}D&#oTA);utnA z1U581n#w2MMM9UTq`e&<69Rx{$OnNPKq1ICT^GX>zN5_Z{Dr)HwowVRd+mJoR`Ep@ zo@vgzh!P4EH(O6)i<_%Q$3xr5IX$HQvTa3Wqir}kODIugEVjdI9*={uH-0U)RPT(> z#ZhIcWQ672{zDHv5HJ#s6d1&~p@Wm5h%7ep1Ce>xG#)y#hVdCF6V6v}_mn7^6{{7; zpU@&Iv@cXlbzAumI9^Q0qKWzd^LfM|B7_7ZN~z3&zD0TqYPa^Zn zJ{7q<#C2`tcL_xQa|Q%1LiL@Sd_O#$WizcB8Cl^)3C%r(Z~(6Il?f@7qVVxS6_m#I zAbQWb1d<4?1Set=^jyVV+5ySHCEiaqg8NPxs&Z6QBgz zf7B7XW`I3g4@<5YxF5)LS%@tin2KZvsL)VTt#^`gLRFB8DSPNtm#fgg zd+ObDTc+n?pvz6A&64ue6V>RP)(To2f^>Ch)gw{D1PiHp+%$jfkI>GL^TjjibdjrM zT(Fu*J*mzz&9!DM3+K1EJX+ld0f{||67BV|)pky*yUoROdmN&3bI>hlsnn@EuSJmf zOfZ&6BsbdaZ^Z4}x0n4>t`jOyxlx~Mi*wJ6S@cQU{#@nm9@oEAXPsbMYe#L{K4V#n z#!hdO;9dJJ<;VH{!OTnv07Pyqi}!a>8rnutWhRv3;WGvUwb~wBT zW*)sFUZ=~c!(T8eY%JmWe`QiRA zYUx_$L(%r=_+;ox`+V4U1v-=ws-8Lff-ogDe!{2A;!fO~_B<_odtcBiu)ojt*=_(} zX7w`_v{w)gp>JP&a}Q!jG5m<(GlrnL z8vFLd%pDOkpu9;Qk`v8p3$}hU4eNqC{VE0x=7L*!aNriqFkB0KS0Re+&wELR+Bg$i z;;9tju2z$FE+kkj@;Eg6Dhp5etSi$8s^BC@5<(7pJ?{{qRRVgTSqoV;!*Y$+Hvj~H z|3$Sf%L12Dpj-`j%ZEiLk*mrnIMn#h5?q!;4WZmzxENXn#;Z^SF9zsAIVLfbQwN*?NSMd$%pY8BXm?J>kn4EXr0LAp1zz)RWUHo97!5{ zg&`m0el@;w)&_442$*s1mO3W)I=;M6V_jrW?=H|?&EDe`OUsJJd`Nwj;n2PgR;uhc z;@`_`&=$xGZ3C__S4GUx=nS`{7E|d^SSA+&Xxe5yk$G+@Cpx1JvWoqWL$`%zE{RrZ zv+_6qH&uStH>p8VK#T#GK0{oUCA!^w@tu+!{yz9=iVjF{z<^`(fLz%y%I}8*uVNSO zb4v0)omc7vnAet1sR~63garR}4bZL*!sF!oWw#J7I-(5zvJ2cD!oR9EsbPt+OkCuDD zPL56%GbX|0hBl3R`kkNK-vUpiL;Qfid1LnZVizqsYGS1#l*9ap+h5TVPSj`QGL$O# zO9Cr!=8HJ1yYv?3POflGDz|ebghf2M069R$zj{5=%+WWo;v(E_i^<-dm8(@Cb6HW+ z!liKvz;!*hp-3sydI1hS6j0}^PAwY132+~Zvi;vuFL`4}5vafIm)f}lu2;hV^H&5`bn)X^u>!U({f#Phva7Li?W z`y`*EiQ{_T;l9?skW`*wJkwFRyMw;S$b3OstrGgSW#v?SCO#Ycw~zJXIHp8O)#so1 zJC1~*Tq)94DwiWRmekX1c-t1RCKe&a`DsFU;b&Y;sQ@& zm^C{=Xw)X=G&`Zbpv)HVzo$5>E(nwcQZiA@uyp`+X*+-h7}$l4h_VKE{Ww54tg09= zyk!qc-yjQ>&PNNHeF;mvpkj_i0eUEF%bFG9DpKa>hTgO39=~*_Nnmn-GQ=Sz%uXLl z6pdgA?^$J1MOn{Aw|Kq114SNQ7YBb5L|G;=;K)qTP{p)W16+0nVqlhrQcKAxAHZx+ zP|c~cXiVM#(s=o+-D3{vjBS~iqX>WYctA?xLRiR9868Er5o(&^egIbdOE41h=Ga~c zC>kh+g%CqZ4c9ESl$TLm2#aAzn$=<|fdxv!-ecvqa>UOr9Le+-Q_zUg%qKtqr#2OsEL0no_8AR`)!@$^?U408|UR7zMSk@b_JUI(3$d)Sx}S%%zV7Og4hX^ zE$@tk%CzVxWFr;jHKjla)D}n41I&oFFjk^~wCR*!J$P~tq`z1p@btd&qMq!K*7oiQ zUvcM`{j@I_{NB;j(q#c&(za#)A)Tpu%owc(QCWjgs{n4D-qHt1+{G$aO=1iEE&B)X zjS>5^VX&;`SavnciQ{*~+IogEnM_`y2tWrQ06_IDxD0-&-pWiH^4%58Jk3 zi=AmRaeDArLf_u0_b)yj{*i6Z8S+8<$%gF;@Lfyx&8vxD6VdT^PxVr0{jDT*8E z1{^k*WGo&!gCRa!_SK6Osa_lH>I?5a{Q%$$k3;f*r>_5W@hO>7HHuzKgF$monSI-d z{~U@945AV~QVhYfzrLJwnB^4HTQFSMB zk{w^{a<84TDDk~KPt|pKoq%z=)MN>~rANBVC&l2h1AsevJU4uw6r6zpds65899_VP z7G81FCm5OBw3mjtw09aGw@;cUPfCHBnY=0K+|w`i-RFcFZ5F;v{2zZgI$Rp9nf9;sr3xz*TOq;_)S!2ERm8f@`ULytTdt2qpfO`u< zKmE7*+mAY?Z70o=1=F(rNy1!5qn<()j+bG$3@?&(kviDT&B7A`-?r7y!ih3%l; zLZzUqukcF2R?%a4rBZx?-jY*LL?R|oLg_b%@B2|mVqka`$>Vedfx3kS{CR`|%oLSX zm8q39Np4`KzbQQb$Y#u zgFW9$C6j-=(LwC%Ccgq|KBY)4^7`9An|^6EaqEh#!*901cv9V%;gT-a@oys-Xj#Mk zX3qfq5SQ@4Yuc8~4=zL-0Qg*N9+_rPb#MU?IGJK5Q#hcY_Sd}QG%ibmxWrX@}@g-tlxP!CcO343zX3PN?u$s<#SaZh`iPz$}?44L$ z%c2B)_wMQMk%(8HN(lQ9^;5mYO>nNyjqK#TB^CdWagL|G}ml7An!wliQgqc zX+^FdjnHD4Aeh`LD0@Pkt&R6Py;Zx*Dh?Cm`&euQg3=`y@Uc)ML2o4lSArSvvB}fh zU*3E(aYR%Om5}&ATV*AWsQ{D#vIBuX%-n*4EyS9MXwoP_WKnBLvGbQ*%~&Dur&k7| z0Bw83?uP)yq=0M|yNI;ICO*(^>+6bVvDrCPK&a#YFBq{x{uG2`VZbpfE7k=BvKCI= zBkdt3r*2{mpRmOiH*ho7a%PSpJj;VPzf>yHeSm7U>PdK}$BK%rFl6ze z1phR@bfFQKWaH|Kq}i7Ev)U5SC+#1k^^^AtR<1$z_rbME=vnh*_N$|GWIBgK+=WLb zrJmA;b+|6i_i9Fy_syq8I*aC1sjhtY)wT7f?s?=rVY2p{JJ_)GYtGJ`-yJpk9rFPY zyB5Ie_u;M9`Dedh-Ttk_ug%QMfAlwFI|T4|69#}GWI`)!L|9VcY>EW~)@sShwse)n zW^>0P8kxdS_G=uljqx*ld=1!ANv?C3mJvk@HXmH6`G z&?p*ubrl%ExgmY5fmzBiKj)4MAi%(ELIey~jC`C}9_p*BP{4Dew)l^6;gh`kP0-&T zI?E`*Q}D!| z+ElK#x*g!XFBa2Lv*782o}6 z+)KpO7u`{kVikX)EOJrp#_@xfXK#D~@%}ES+mLtB|3tw3yjwh~Sd*>m&Q4-NqCe}- zUg61JML(x1gwat!r+~?YPpIq#^7RCk>FZ!QMR?HfA0zfq(^cc>FyK?bFo4+hZ5-^!GVH8$<7P{(~0`9+0}v z#rXq=@o_1y9NM_u>saYtZDHzF1j1t1NTnzdh1E(jCm&EvGxON`*csEdh1L$2RY&5k z{C*V{p&ypQ9e(L4(zbe}RP1i>-mS>h#}nUK3+!z6q2p2XdaZ0#Tm6|i-{@c1{H6N# z`JBQEEoJgNIli#|pWnDJ?02+9jd->=BQ%fI{EgozXAZG{exCW{TQ| zVhYybyPvZCX_KXhn^uSAe7?4$_w}Lcxm?u@=+z-(>Qk+yi|d1v+vbGF2JS)E7p|Jt zPmiMn61S>nI}sC^Z9x7hYxuSqLM#l1+7e4GGKBWRJ>L=qyhRo*>g{#$a2lB$o|O#; zOs;>CeZcJ4r@y(L_+_DY8C7~C0*`)yI-kYEnsub0QOCey6e48To?yiySI;WH0B_+& zKz;o*0ny*f1R|ahxCwi>mDeE+Nv4RDy_nEfaJ4P`?miK|z4nEoR!!#UjT;76wx4Y> zXaGH|_<=4D|Kf-8CyW8GsIh;M4ybQu5g}ze+FG>2*CpYjU3O;^dsT!6`TlGxfv@h3 zTtC{+OuzO5kh6!n-KB_!ETctKC36oqP8>kGCktvsCO*Y8XViIIvl1vgZw4O!43F^@ z#+&IE-9?R4od!}9gx=n&+xo)+%cmDX)V;B8fFYmv( zZok-NFLiN#{_j0!^!J*h!atw7cQPmAG-8XB<)MJZ}k`Wb4Z z1H~A8$l}|ha}Ta9XGxH~ise-M_qDv6uI|=yF#ec*1s-?6u(ZN)21l zxne*Iw>K`O_@N3;DyqA^u@wo-ufeG7@n-;~P;?eJqjVHx;YJm(g0&}1W^y&&EfY$^ zb_guc@&iE;4ErsXy}>`U2MJ?9cOq!`cM zG#303mSUv*0&;tP=y?UKJPl))ZTWG~_xv4Wf|4UF)iAWg!bpla?}Ax;-&V*mCuyyF z#t5>uxQGwfkMlfhV}n|duS&E{7n#aLe}~zhFI$0AQ3U0|$$*ya_|KaY4|}G#OdGF?dS$@4%fsd#5fp zL^UnyV{>!cfvR$5c-w2sbKW%xEgw7q&z)Wt5R#EDeYOl711BEY+%(KQn*xo9;^FfD@g+Vp6x&yA;xKxkLo;*As z#?UIUmHQT6s)FRq#dQNQw-2ZeqpKti@|QszeZQ@;^XWNnG(%{l&jB-;P$d^5o1DuQ zr!LT@<1{OQU3u^v4yhm;{G5yztR`}%K=u(720#>rP^?cuGDJ!>ES2p45>(sJo>cXz z@o|jE3f(bjUt#A6(eWdc%wc>AkVroykJPv@#z>-m<2w|dRL8SYmV)V&AEZI66|}+o zSaNJK(D-+V1N;rTas0Bi!G)e%2Mw+>pezkd%U>rx`12ee9NKk@-she_3E|~+(%lBi z^$jLMt0N6%m#Twd-JJS7qM9bAfEbZikfG58XGE-;G=i1R2@19uCl$U3B`rGF64e+z zNZjJhz2VF3SNz8Ujij0NJPA`IMEQ$GTd?3jTz3F4ONssKd&seQbVDihPzO_&d9rc* zR|-kl)K~?_ed;Lu8rwGWRc1YFQ}M&pb<~_c-k?UcjQE_5%}{ERt7lbvY%8lmwE>~u z!B#{$}{%4K}WkJBA>>Mbb`xc&PvgKme>^@q|K+Mh8$7YM6>@A;~?fuJRZq zlb1JqkNO*!!iFg>ORlBC9dc`>U!4>)$wQA}%DMIQ?k%ZW9#GP^Y3iWJzgKWN+)ZfA z^&RT6Z{s!DP7zk|;R!h1nae+T)#s+~54|r%5hB(SwV*osWVG9qiol;U2s)O{f<=yx zr_FB__c0u2&_n|PG^AZ76aI20spiK6d2$1qzz9I#0hFJo4ZF(H{j+%=WtC^X;Eczv zoHak~m`>}`M$F z2?KTX{hzrXmCSB4{*{xTV-SI-c7>ZR+JA?LAG&UsD-umv3lNqX0k%3X?q4DBly=Rb zvSpw{4=q^Tz0_-&a&q6DJ2!rQB}jdSl|^m18Lub^vrR=ezep-1&{C$=a^iIRiL10` z=M`dKo;(&B#h3?RAJOLs(5(!*K>tWscb_<5(+i{Zr|=Vzy6uxTG?})m1!AKhmJYCr zi*soSNpXSW1_WHHJ0I6)p9+?{YWw3klj~7N6(T3!F8^Lcn8FOk(r`GcWQs+Un?3;P z;J0pYL_QKQc&f5*F@dAdJ{p#Q)Rz11)KUJUNOh9jfbD=NCs3E=Z$VW1sRF1oBr^5z zhoT}l4;E%T|HJ*d{#=S4qnoEb8#t_5l)3vYv`P zuU_KqW*VNr-hRCYfYlYj&8)6Mw8NE{bwaL!q`Zg@XWUI+eZF?=uURILka_8$(jp>H zQmR%v1=g6w>bAt*@Y`Hx)Tm@>$^~2Sw(wJRd4&W{Rtc3D;xXhjYQk&3o;7W{Ries# zORTv4|L}md$nKMPeSxwHc2%5(ZSenl$%QaO83LwDI}2}Z*Ul}++w*>_Xt0n{Bn9%XLP6y{?rBNPpINRwN?v_Atw;$^PWTKrKgSV zC+6b=G@S8G8=A*fY$i%+ZncGFDmqJ%M zZZYC_i~PXzkiEaPu`wtZLue)cj@Q4-sshb4Zi<_EV5c+Z_BIP|;TmRvm`U`$#l`<+ zvq^sJ5?k_3sx2%7SLkw^uu`6(#e9b4MmzJ?CJ&0n=&Quvj7f+DL{qTQ954)?wr$TK z^!he{FpW$a>N=YX%J+R0-4<_!ZGI^h=lQ{O?8JbkSpkw=Nz4;6U@=2*h4J29L@qVM zvxCi7{nQ**AY{S>GEx|pixgW=3UsrzbqPuM7wV@Znhx%czStQ)ZBNclz$n@g-n?HZ z9Gsnf3E~VC0u7-?xpM9*IXB^iAJ~^1nAI3Hplq-lS^JTV*vOuIpQ^vjSZF7@tm?nt zgka9N2@L7$8cDT^=CF~k~0CocK zF0typm26F8SKls@OeH^MPHO5rn3(`<#Oa9#8=>bJxTH1GA8j17x`j#9z*$>+YE6opn} zn0u&yBPKjAU=nQt(qD|=+ZAnebY+qT`Y6?BBRe>zCrW;DK5jQ#`PEWRTHc_iH@owY#_dM{CYfnT`Lew8hpU$37KRRjv-Uox5Axk{d-#)Ay$aKZ`y?uEKV0;y>saPaZ20kxeQM@i z&i;upX)FI?Bgtywz_kpNH89Q!>j`erzzTQufmIxGPByPN^HlbhbK+z(;Wkw%5Cal7 zTj(y`X1OyEcSE*XB+1F7VkzU|C<1XQP~~GpF?l<= zOU}DHX3JJ{oWzJ}Fm5^IkmoQ0)r=48R+!D&*e`X`V-Ge zs&1B{wzg;jH)vOE+&k^`ymcX2&`$0stCN`yczx@0h8qN2K`4eMt`mV3<0=||gd`8v ziUPkg@CrD+uiI2{cKmKo_DFGixcuP5 za_j1X+r6~6W1xO~4HMRKq8IZ@B|17@q>Xm)-(;X0*otoOp` z9%=cEW-m!I_gmkOX68cYt3x|_dx`le5cjx>{Af)=y4tszhok4$Kk-S7ZJ=k{?4Kmw z-2jA6);X{G=!O<~bYY1%A*3=)qUHE(S7$BqPMDlbyU^-98^Qpel@O*?}t&ehj z$)4FK4hR@{gx`KDBf8OKeOP3b6eHRc(DXqA!`!J8RTV6nugM(94?7<)8@2(f_l-Cr zCuG{gIfb=pPDzz6*t|13so^q{1vGKOBpRrpazkrn!+mIQfl%UkBT@1iO>(XzR+9!L(hz1k;DGStSY=m%Kv6@|Xlul$oQK{-eOv7@1tU zJzK({R{$xmSm6XO>De;3hDv$^^$^V`CHDUIWw_6Jn*-nOLP-A~9f>c*|9A)c=K@!_NaIG|NuFLl>G_;UElA?%O8r2X&0=Taf4cbOV+!gB!xwCahxTLq={mAUJ_xNe+sKn zO%F z6*U<27cxv&*_bM>rr8VK9++{xu}An@v-Hs(wo2Jpbz9SlWmy7n?3BK6`4p>c}PEX65;;JUv2W19z5{+ zKCK8cBa?DA{l>4T=c)Wp&OwhqW>$zVt(R00%%9{aYJw1KPS?Mzj7*k&3?)yx7}W1Z zs}xWdCv+$bPh0>a$P|ZN!dRFlQH#!87>Dz=$Xbo3&$kt^ZQD7?A0R(JKpVA&*58*l zGk);evQgFc)jE12!q?)O%REaL2r%fZ#+iz@A#PN%rMbHust{PE5`X5(zodXnpiK%k zL+36x65_qY{`yAettzS*ny4e2@^sKdf>a_^leV{JOK*-h(nbEAOOD8RjVL;%Yb>vh)T%o#R2(7#1!YsR8*9} zNtjTb>(hL}?v7^vSEef;zxsIp!pm4Jd6=Y+utD(LCb!YP?;1I^ClBC~OYpS+%r5PD zqrgr7aNR*&C*GaSm=L%P>{-Ij0jja;o*2$;J8{UQAZ11%M~OX)dha$X`x2~H`AjVB zzB}to%sivSfKW|*AV;;XamUGc%r5-Q(6**Ux3!Ps{^roM>DDt{$Y$?VxteX>?TIC) z(eL~)ZAB~!Jd3`+2s$n<P?&PJoaOPi%$FDy9KzQ_u~4b+Hr++> zgGV?|GMR<<0*E2{D8gmg%y4f}J+!+3p{^r7aIHX=xXk_NgL9$2brZF`nL^s-B1nAm zumZ_mjDY}(x-B7S1Yu1Y48bF+_4XycQfO?$OwyMRzOoUtUC888+x#8dAH+{y26*e3 z`&#u90-QhYo%mO-1&F@+5GJaykW=YL1xN=IPRm@-?*kc9TP#T2xs&V1Gsyzv|Expi zcHp;9JOxN_AZR%^!I&;rq2g4pw3~4i#-w4B{2Q1FSz%gYNxnhdyMDT)17p}s7;biW z&5<7MtFljmH62?V+;9;6-w^MA$)55dBDO$_|#owBep+}HP(4Yt+dJjy#+=&=p>j4+jwiej)BzQ6hmNC zVt0+Rn>tgC)lO5O>9ukO6{xl2nF7Z49r&JVnwdn%m1x9BXm|J{fM{8(p^v=ehP05~ z(va+jclv?49{2jZO`vGw%&?>ydw#B`%akM(foC*6`zS0Xwh$j?^1iXJs%C10go?*uO+Q)8N;Y|(IYz3$=F?m9ToHhX}w^_X9fbbgp zee`Xs^r3}+Lm(yg1^@4%!LFoMT?2dnkWFT%;9{WM*KjF!ev{1Je54~3uTdFUBZsNX zsxy%1zp-V3Y@M$W&5)+3`_3qkZ~rDT**{(XtaZ`(r2eQS>AS`jHLNdCoD{ncV`M*0 z;v0s;#iU~=*xyRNg})#Ua5eN#Mg_ry>H>o*-gzdf=b$Lc{XkzM$&_tgIz?OWKYXF$ zOAw%WO(iczGHsX!Yn}{-MIQcfqn7)!A}!6QIvt%_#oKfE#mM?LY~ETng1z#k*Wzj? z1``Vp#;b^dmn7wdJO7GTkN~QGgsN%Pyx#I)wq)%DXfJ5ftx`p*27E+dAW38q%m`+RVPG=3{^6bygBm_hM;N>$4)ZGX-7Wi|1tTVdm zhT&$hvVdWFU>Y9d!W!l%+@eUU<(#qQ&62mxxqiQC?`eyiP!X@+VlVaa3z>W7zH)#P zah80s{NfW-Eb)gSKX(qeP(uXp4@0CsE-zKxwIzy#*p@f@qF{wwVe}?>s-c$O>FJsx zHx+Qk?HiugujPDG^*w#{n8&guT_q|F@&#t0?9Zk^v7q+M#!q^2pGBV&_y9ow1AZS+ zsVblfSqX$qF)BvEQ1OtXCm;Aku_E2VoCF%panU?{+zO<%@moOFt&2HR5bG!8j}k{N zx=@9Z>tdQW;U0Ss!$)i`x~Abr9XLMndfDQ#)Pm*XiY!(ZkGo*{$R|pVz>e7y#W$=) znSo262SoD6UB}Z|CfIsa(Xkd?;7ckiS z8}igelNOCC2rx1>CgHE)igBJykFf-MCyR$tbLq~IX|7oz0mdoTl zoBVz}BUeg^3-+fiVMI(9WbxMBgs4j#EG9(KnFzB2jrG|vH$wqO|MCnhKh84b_a|hK z3APsAjNU*%U51I1Wn<}!VHOWrbD|wXLIyz_((55V$)Cnqa>2Fb=#6B<A1om$e`pCpj1k6XaRvS- zEzdHRjGd3z3u#+?G2I(mjP+T`OeUF&_iOX~}-681+t0$t!?8%}U{DF&E zPIVY9YKFye0xWQ{P#eWXPbO&u41Jcw$=XyuV019v&0tCfc+g;Ym`Vf@gYED6o_NhI zkx)SvksX~`&Kbjx3lZ4Bsvd^fU>~>|f%T8xqB8yr2A!z7CfKX5Jjc4=pn@`WXg#;; zW{e-smqmo2X4*XFv+kZ2v>XqfdC@s%ZY7hvQQH{$z9YZw_>;$J0%*rA8}6OP`p-b2 zLK0n+P8iC_=q3I?8!7M7ZW+&!Izp$6=&{`1eoRvn^|WGebM`-Q5{(Kp=+1CT9k){F zudt7agG#M?-3kj;+@Y=s(Lj^c*MGhw)>K=>SFL84D~%`N+y{=SFdoElpcb*2@3J=3~)BVwdWwqUzHrnR0#&^}7 zTBjod1`KLLnbFGZe?a)9_Uo;)PZDcAnr&D0upPDxc;%sqGe~Jt5yXD|S0JwTl}$%y z0rJ>3$kyCfUF0Dg1;G@{=)|aq8TFS&0AyHOE}*_!TG+XlP2yMegj#99>l+$a(t^Qw zw#Ex)#uHrnx`g61RJcP!oG4kV@6aEp1IpA2QDiOnV!57-GtsnIqY>sj>`>txNuCL` z`oTdacY_c*nEQM*-hXY^vt4F44fGw|vECfEz-DjTXokut(l~)bzuGDR-Th%&4j>{d zIVTJbT}*;wXF?#JL<9yUlspVWtEHq$gY!e%iagCRV1~_F$ZPgLZ#lG&i!sQSp^8kB zrZ-@KVj* z?ueKUZy8BvH^td1r`u-*+{udB^eDSx1U+7b55)?wGgj~&-l4GyXgwRQ24O)$H$&K< zDeMshT7Oj?noHnK*m{kwFK_lQZ#NEg?=#!1uhMhckZcE@40F||t!7?&+0R1-c$U=j zeKx`OYCwE4o=@vIxJ!A9+x6y|5#S~Jbow7Sj<5B267Ub6W`zWK|1p}It6j2Wbta#A z*71XuM$rky?yXn5d%5>$G}6+YhV9k zFx#%4S{}AWxNew0(AIK4MhZr0T8Fv~ z-BL{ugm=rLxleG}di?zT(#Y7LXpA$vlqvDa0w66A}Z9@I(Y%cnC|><&UV zti*`=1soREt6!Ykm9J2En~F&f4(^rqbtCP%Ib6I7Zo;b6)BCU<(7pjd%#=0e(59{= zOXY?mG7E~8vIIG56g@E;&DI3Jd>OC-?dX{8$GraU(e}&#&VKfS?|yG6>NCRTo)&n= zaC4idt}zrM+#=5240p5y1e6I*GcK>+A1pLBqjSpTY+lV?8NasnDsq<4m_f^qnvXR! zHgzguK)pWarQ<8%&__gFDeo^{tFOCQG!{~9pd%^oeO9AXU|2F6NIFj`-Xw~S8CO*o z=nOCFKq+a_A(xnb^ol<=MON-q>C98OBb z;^y1#hI@BH?GgJPj7bb1oE?7fEwnkX^6el4ZHd+^=d>oczc;Rd=O$by=}lt^bZe@; zSZ=HV*fY!=U|5mKw|jJ*TTJGWEU5m+kGB##EiU=q0$`Fd#C80b0y`@olGbCk1@-^B9~!IFU(aOF(EdNBck585{(A_F(mFvUV+#;v0?}m8ko=oKuTuYN=k(>6(68 zQMc}t7%)i9%`1d~lR4r6n;32)T-=x#M)8tRDiLWN?AuY$UObM6{M#E@gM`s zyk3J_uTo4=Tu=)8XxXcK?J^~Arutk zNAAYMz>oOO3zBbM%d>>N@6_bBXR+TAw*?hMP(v^gv!9~XF!OMZZ(Wj1gD)m)(>CyN z6{5OoeC^CC2evtKQQk8oppEPUw)9wawM<#{Fi#e+pE06$k!Sb-OmyLh*k6M<=q9ti z@)oNJgRktac|vSCdzVCZh-s<)vj*)XJDg6T^pi6qHUK?b7zkW@xpo^K~PyjO4jFWs?u&K$~&+gqn~ISbn^Ub0|vuU7#0xj{F;MyFB;ySa;~|=qB>AE(mWX$ zApjQ&Ij3tZ(99kRkVwA+T&B9*5UxNjURGROk;i{HX`YD3XQK-Q8>c0LH8GhX>8|qo z>xo<(7cYnYBKA#;IaHFYBCn9FVx&)ecO|nVoK8r(8YXYtO#8xDnWe2|4HH~RtKPYV z%jGLe#2@sUl)H9|i3pOpZO*8Ei-2#E!~WBH5)@7XqgNY5m}hv+xW2YAo0+@90S1+> zgTR1VuVza2?vfOq$J5u1SUPxU=&F{MR*lFN4?HUW*d-gpm`0PS(+IWlN&Tike|;_g0g zPhx~itsgADrMRg)M{vDsdFWU&skjBLyU0YdMFi(}tTYSY?8+7tlw?+j4)B+BhF0W4 zLf!#xjHLj_Clv@IB>={O;qN>Op4YfjU0ZQx=3#_j(*)qaC|Yq+)OEMnQ*e#S-`$U;uxL6BbLo zFA@EvPaW;*OhB?IGa_FIBUTk8>P{Kwle{<_4D3GvbuZToNtwGhmt~25Az@u#u+~B^ z#@i?2aJPMn(NfAL8e-|LeYmJ&7H}ETm1+@+7gp6#;{rWj#^EnD(E%eZ(2mydRpY*1uugFpFY;=ck%p6PyajXS^ z@P_VBox=x@Z4PWTSp|RNGXX07=o*|QbxFp}Utj!26Hxg^~;^+71sJ&pCL0#D(n4j{4NvGw-z?DpxZU-~NF^2yR$t+wO@cc~jQA zmAQN9SP*aFm`lDQ;(P#TfQ5V;76a;3E_d&QG~b!_g=^ruha4dRKE$CzK4G2haPIGC9(Pi3m(%WO?nxwvz}=+m zC*8A`((9%JrswXxi%b zNUi+;Fc}%|(AnE0qb&kCSAfRw!(Ns%-XRS#d#IHQqGMsI;Saz~q8ee{IRDzeJQY>A z_k}8J;dAn$zE7l(*HLucV7`(O@PzCvDsz+p`X!-V z)I${L#$wU6>JxiA+b2d$sa#kn*a^`UM8CWSR5N}<7$~>wZZOCX{UsY<=YMAqN!6#S zRq5wACqR`zKY=7RD|K>g7xYgg32)2ffBWbyRb&M+TLk4!#G1r;(o%vQsEHvPT{2Ge zE57EYAeF|dYO5N9RV=?y+w3fQwq7pyKm22wV}=C%i!KhSP5EF15|2(@8v&Wt>YI*I zC^*LmFeWs7ze z9VS8NR@xZ!94GU=7wSrXMyy4XRhb?Rzl9R=aNdu}1tMUD>7!I9ZxAH9PR!z04b&U* z&|*-FCp=9eTs+foQ>6a{&1_L!XP(qM%uDrk@h@D{U?WMEe!vCn>L|sN_`Z3zGi95} z{PPsFKjJp&2sgu793K+716E65C z-w>^UyT2|9AZ+4AmPe93%@Vi8>5|g!SXY50zrqxJi%kQ8?}2wFc@GLP8KLY(PNH^Q zRh;9@wDx8KMT={?Eet8cz)(olGv8=Pc|(@%qIEhb!E$ex5vU*)fB2Tr15%b#n&<6J zw{k}Zu8{>cjFdTsy%I*|mdnBAHeS}>uo!nX^%wnOV_{b3KkY7N5aOcOe$~A8I*c0G zo-NU2w#?amh+4h!nP;T;?$xO{fzz@^fh~W@Tg!*qCT>VIJS{%>MV?G^IoPoZ38fU+ z3kOX^w)G=GX5f+XU~iTf$dn`W6UC6AqZ>!`U)zSy(y?QkU71Yep;>n%bMh){KRtUQ z%NE{DIu#C|L_A7fWE))Ud#1AE%>f_#qjSJncgX-h=&1`jrx)aGRdKNNe112x8c;cG zZ?zEUe1UD8q{3CJ<>Aokr-}kll21Z42Rt9f=2$8#de!HUX2M^`iKg;yJ8N^~)DrlYTEea?)Azm{Lrx|Fz<^P3+R#|on0L+-l1pd|NRPGM&}W|+z#*!pnR@t3B$nA)lIj?3%SXM*l^ zM)*oj@1=ic>NWlst4Ogjl51qTiOf5v*LHfMT_(X74!zVJd&sea@!(O69a93+O86I# z6Gej(>vCTA@@dmL72fLiWAd(tvQh^2EgJlUZ(bq4=^N4eT9X|vfHx`4^7e~qc~SBeGP6f0q@2MFXYxIXvuU~m4VzLGj(rEEHR(7 zijsS=U+Ime!>7y!=Yi|IMN8`m{k5tZ`+WM;vE7q*w4QvhI}umw;%nxjfi6T7S8M*#l_)0i5k_)pD+CTD6l-n-^U85t*pLu8WkOs_Avt;W*~j{?Q{Qi@-HI`!HC>yt5u;x5Mk(+ z<_JPW)v&U$lz=D|68aux*!UDC0g*prg;A!FZ}Qs^05pUx6=$sH=`t}v`}ivYacamC zxJjreYVdYWNnL=1mD2aI)$*`LhFWtCVb~{N24|C%N^e9`>dW4d#r6>6v|+||&RdAp z`zz1lI96>kWv?S14(r)!>2YQp@mga<$Jrczrlj8^z>5Ua!|)%44QW~*!zr~ibEsBt zOh3!LU(m=$b{GmXgc7+YJEL0^JlPN__IwKVH3y^UC6Lh*#=}GbpMpl7X%8s072K!~ zgj|g;WE-JI>twm`*JZPD|E_iZxCXK;#5BYQ0=R&sXb~0v-!58(b5MdVwfcx)`B*G} z*OO@>lie<~INphP8fkAqzj}$cviyw-kM5g@VH7x^up6{crjOP>5S`E%)6(9k$VX>_ zc1Rq$Toy^l512xlrKBa!hRhZbwf>vjc^^FSHQ`agNK)UgQ1@_`3|{PuP)$$)M z7DCFR`G!m?mzY|>NDMz4$?zJ9uCG08N6z@>E03?2al{+@=)IMR!wGfg)s8)BhH}mQ z(M?R)?cOoh%{=k)se3Fmo}2wki>2UJuC|xg?GK*Mka1`Bs=xp(n5m_~rW=K4LJU*K zX~VL)n%iA_q^{)T1ZVE$?h9DHvxriGl!2K(xQ9z9;GhNS9~hzmR%=j(XGcBauk2_ZN1eKf`c#w$m8s@qlEcDyuvtr()A7P=`Y|KD+7gNDdVtf=_{RoFE=?3DW&r@F7~5@rfo)-+7dsuu`2-hjHEFG)ge^Pf0s<~La!%lJU6)=w z=2_-WZL}b!epEbQGiH6BcQz}}Cm&3YvS5|6V9eY;{(VqfH9s*J@!y@I;|+N|#{rHy zLmZZfo2%VVouz}<`ln9UH~8T&Q`HoRmY``T-p!QbhyGFc%t95HbiE$djU`1w{IC8# zo+e>fWPfJtvD^2C2$F#%IxJ35;54rvjHn=SFgIzSI$e(nSb-c!4Sbu0@SrfXC(9*t zXW>qbR{5aRe#U_iDOvPew=#CSDkPDSx+c=^t=^8l`{B%Q`U~&Uv?rVjhkBlI3%%3L zi=Hyv8?V~)S!e|k@GDt{MWy)e?Gg(^TZzni$ae9NWu}jQ!pM489uiIRwCv=a=g=~^2kvbQ<~o!*YXS_LYCH9K0Y7r7H`ewUT~<`axtSb5PVjRL;*+XQyvS(1 z>&UfS4r^O>yBJ}+!#4Jj6$t6G1PplY8b|vsq%lG;qp@=B4qdC%QRVQ$pyKWu$`JdL ztux;KX|F@zMIpil3-HPFr@hu(VolGDEj*k}*vrVJ2<9UCXRa9jdtIQG2%Rb#{I3bv zEK{Tn(k7}ntMK04bj%Phycq?T-z($0TfeBhsnZ(2R#1Uj+-&-8vc{i^H2=1)H)y%u2LK#*#ll4bx z#XPAIbg9mkd`1!mFCaob1Q)3bs`1;t2vO0^srIaoOFIIGTsnPSJF&gPO(Bq|Lnl}G zeI7larhcPMeD*6MjH`U4BX7cje9WtxD1}2aYvgetj!)?i_s{o0(w(n2=Zl}-E0oj2 zYL-ivJ@@(tr*7w2FNHo`W^UKU`O|6ssD#Oqh2VpEn7dXO0D=Mzmg+W-xnu@-Ni)+C zV)1Y%nrP0;#H+SQKm#^jG1R&pGY8^Cix95zjrO*)n9CtYK9Q@j z42m7D)@G+UYbVi$S_;j#(Q}i-!)Jb%E5Sd&kMn3sI4BQuUM&K`YEnEekR_g@16Fp+ zxKzqp>^PA}*=qDaUL%ViXB(A$NJ1QMq{lOm*^gt`on$4SXohVdmO)#b-29vp9>GEB z1P{f~hl0^4UN(0yTjSnlYF@}2{8HFCz)P;HV?uS-vc^2}uL~lF0@}=OK93&QBCO^? z+VC#^ANN$rb}65xXytX>RV4!dpdm-_we+KoO8*;nkzuxE!pcD{mP$dTip-+-)Ts!S z0r&|r@m!^Zh>x5y%yaSRCdz_TMu|)6z9ox|G+Xb)Fa$YYcsU-No` zK(b!nLF>&$@0vQFo}VeZg*|BsePVNb_N)a`!Aov-EZ!@QA;9X?qeuaR3(M2aWDi}BV1H+ zfzR1FALMI7{5Kt>!%)cN?;sM4C>uzgaJNscyd|l^^>Xap~HL5{K zfm+*o&J%JDPhmUC1&W;zG)7;wJ zv5WoOU}4KJk5)I>Gpd4J{#g-Tc+#$=Y{;n`liRED_eiqH5|y`ZB8Z$RXLJQ2-9YM) z%?Fk+tF>2#5db+&qo`n>f&(N*r1Bm+-H5&-!HtyNVR==!8~tyO;GjEiii_CdPB+sH z*yrexLUDRRk#!CQDjhvqwud7*<&J^zJB&xiB!}1RnJRo}_{Dh^L}6~JR9VVxw8FVv z*o-RSz!ICx?wB>)st~gF>K<_eY5w7VT>FLDl@8JK9@khpUG4OUF!P^eIQANUHV^hq z)@kdiI&eyF2-o#)Lz0bKE^ttPwT87s4wiEj^}%MB9Ox>ma8NtooJ9zM@>id%2o7LF zaO`&|OCC0VMr44;I|52kbZ}&*r)@i|wXD3n#J%qyBaGwVrUq!k1yY zAux-3XTH((?)mM_AR?R0TR4c)keR?uAx~70odS~k9e!m??M1vd)RFp2V_TCB^xy3I z1SX(ePGY-D*afdR3M|HsRfO=t@!Kg5gP9YOG>T=>CLl}jbpnyrfVYEx84X72sHf9P z_Q^bazcD)$!ZZv@#VYm427P+oEaupLDsQ|>`(i;}%KVpcRdd;=>2g44A0KAGr4y-= zEt1Wt$+Ij3(koF$Mo>p6Fescx)P((-p$MF9 zIGWZC3HCh)4UkYTbNczUN2IF~POW8G3xiT3SVl>JKh zt>Dl_?sO3p6fq!fsaYJF71b1<4sJfQOy?<3Piww%y&CCP! zTJm!DTr?V&$oq}eD#r&z3cd%=x5=Pq;bUm0l!8Z6e8v2%O@HF*=M6|Tqu4ELDC^A+ z`w#|$v=_YNc#sF-7S-MO@4{S_31uD2XN?U)ygMi6>av|uKl+H~U38Px-|{S#r?2s~ ziRra(14t$m+L<&?vY?KRP3$srRy$en>vN4ThLa{XqA>PF$aNHgb?LKnT-`2#P|KGi zOFr>~xvI8+n&|SGv_@JY3ccz#ku2eOw1z+AUit;MP_P5)q*hixwZx#1lweK~ePG0Z zTgly&jdai}+seqm4SXCfmI1PCK@_+Y_w}c&mH70|UcIyLa*sT(fmF9qDGYq;G3D>D zSV>(Axn6kFtHj4#9GO|ojw>W-EUCKcsG`qX)=a@s6w@eOq?+Vx(ig|iCP z+D+Dss`nyySE>jEloSFyISIP_E_60(jhTf~54e*a`TAXZR+dZu8Nb( z2UE={dvlTjuhXQ7nubSzFqdc|o{B7abR9-oQdkIyQ8KEB?ma>ArQQ5TZ~Rth1& zsO&)V5Nw~ZeRQ`%?}j2v9{!|SGzgHl477RPC#Z<-X$Dm)as$F1v@3RI+iT84xemX{ zW88w^Vklbo)ZZVH<1j#$PzNDigv^Fn-j+$hY4M#3Oi16edM6Qa-v>gXUvW-xhlJGz z^fQ)?lJ^Hk*|7B*IPvz!Vx|;vPxmx-#(i4t&DjExFiZGcfKH5d_&Z;fQQN=Pd1|CF zinZ4>(4UsH9mTwZwM9!3$jfr}X|en}*IcbqARZ3axk~||ISF*#jM%LSbStPj|9_TH zr(N>Mx-Rur3HP2R=Yrkw8u-~>pjdPX91Mc+(g5v89ZKfWPXKnqGLCN;u%=MPdvVV$yVtRzZwkCC%A8VYGVvsX}dQg@dGFErR+ro*$R%^ zPXVK~o7Gd7htscPd_iDvfF{A=>$4XcD3$u!;N=M6YPhmJHnsE6fwF|-ETB*LU6f!7 zK?DkEwrox&0xY11rICoFbdx`dEe+=K0D8-@Nf04%8v$w{7p)Ch)znb|ZL8Qf7#l2| zDwfwr!Smv@+g`&o8R;A(O(^&QII{~eP_Z*ZY9$jGQlYXo6b>QpAs^~D(YcJG_HekV zFTIp;IHmmDX&LA6tD*+&Y!tOe+YjuV@wlDMl5{z9c@LESqd#`?O6E&ssBSrR^djf5 z1YRmN?LV4|0lEUESgN_s3B5a5o!C%U%qe2}x0rif@^IJR#_vwu9}utA^ZEJmg>oOr zRfs*U6J2WwNgnl)XHZhRMD}KwUr^k_@yY4-}0`Cr}UB zK8IY{QJbRP5YrtIg;nhv>#}vlabQ`(G`x)YB%Qq|yigKs_*^R$>k=mo$f9ik4aUQ> zw{b7dzjd4WbzNgSTl$UX@qwto9{pb(!Qi9D|P8J zbU;^ikB<9>Nmp-8L-$-90gUg<`d3^=mdDay)8LRuu)9k#E1=4>x3wG1npEbhC`bZ9 ztdd1@M^LRIPMiSpQg9BP%v+ZDd-H3Py)SbcM>x0(FudU(6~W28R?+Zr?u~7hVBNoqiIHH#46o-S;_|D9BbExe{nm=wd38 z7*iD*_KpfDDp-ND<54aPzK}BkI1Aswa(QB>8Jm%QKaxKE=OaT&1L1l&Z_+p8cEN

287k8sL+0v+LEh%%dF%J$Y&8POtPysNwWC7p}h{p$uUEG&5cg zuZBJZ#XUnf)frc=7jz&R;W>n0#b4ub9BLZpS_-lULE%*sRAeiCnLJx-WB?SWnZ~M` z6rcjxe!#pya(DS)zKGhEx5m}467g^{nS4WNg{V;s1wuy+FV~=g-!%7axYK5B1M`u= zJmH%U=F6wodY(CQ@07=`_^@7bM}VT_CK70mIrg_h0C-_3fcDdmIlVDa+_n}4mdtj0 zi=-Wt-fG2nR2kHRqJZRamC4~~FAkuUGzz|J7TFY2?gz7OBb-r9;MgakZgzC8!%-u!U}GB) zEkkeY9CYja7PAph#9Rbt+pTP=KkM@LUfg2XW7H3oT{YM=Gz}?B&MuzJ#|OE9NlxaO zhD|{Yvpq2Yzi@?QtISPeN`Y8n+1Y&dd^ibD4t8z|xs1l9oqtc^od;x>e^4&K(QCrg zeT$;_9hqx<2k*8UoZ}l)$0)c1tI$6h2-iA|Q*vkJ5+yk#i4=VHx2#?E?V8Gt zA5nce9E8B{l56DI$_BTXldgk$?vU@#LfZ;7%V^UhjD{TtVLE`Jj^z!9gMpX`Xx4Od zvM_#mGj~HE2h-K)b&ZHrsCE9t1Qy9QC=534wMU3}lNrZ}1o@TdfKn7ah?A?x*Kh3` zIj*TVF@vXUAQS#6T&}Wl*&mtUHADt6c?|Vf)T#+~={(WkJ&0#O?=O0W+0963Bbm>d zRq`MfU`hGxXqk(AG--CS1G)t%4#&{>WP1KK3n$B!kjM>XprMGx{G%4o`wS@p`@2S|7M6F?~w$zS^!4G9j zth=7?fhF2MWIx2pB9RA>>1p|<*$a6;3lreR7sY(AX-@0L*?`PYD#6l>krU%Ur%0P> zpH2}=1BKBGhXlPNqo#l`0wrzm3qOkz0u)$?#Ku76L$Ov~CEuCwbax|8mPD8yn?~=C z7b^if$e^PdEOc;x2kV8@8$L3T0$n{@j zD<%W%p-qK*(Zy#`uw3meW+cUGNEhQxPgGkA3oSa$@7FH49Hx%fuSusgIvPGQem*sH;>c7rQvYFHNb-Gp z6^o??Lr9 zj;t~|ctw;H?NBdHIu=BGy;%fX6bVDnuK5iIKv)A(fO5M4(14N92M>4sCtQ9P=jbz6Gq4cPq$6yPR%R8Km+_I$m4MvYH;R_QN&3xv1UQFrj zf4l-j1?hO$0t%gaS;|HLwA5flI-LN-SNBnstG8GH6;ds!vMzMi&h3UPv z6-rpYJFk@UT4>(J*!2orItp)T)Xj~eO6ZKOM>8lPcE zOua~+RhH&MofdxDkJ*5OI#wghakzR1zeH1cL8%hzEdVYn%bVxvcLr3>kLYP%Y=sx^I_zg`lG<^pCjB=ywcgz39bTPs{&UGgAKdZRyOQK1jo&U|PlBHmP8x%faWG)ak&?of zrwAcI-*QeTo66vF>}k1`J+OiN)|eUUYA4+?f4b9azqU-&7k-xIfz`=-idL%F)N1b6 zK1-QkYX(JdU##^Eia~)4t*hek(dsr|jeNTUiuJgBpL65~P`_{6R1R{`!b+OBv!v=JwnCL@Fv{d!o*ds5x)|maPy(2ruJ)YH;TuN zOq@8+4ShUI`f}uJYTN~%Kz=<})f_^Dy0P`))cX;ry;3?s$7~+`X!^Q7 z#y#GUsfz44k4;RWu`R-s9onRIjhsWB~IC>npx(Qy635`&WZJU5T{^-Dp4Uv83Z9dx( zV!BV*y*kcuea4Mj4HZLPZAEOj>lE{=!xBn)L5^|cyJbYbdRo8*GKVki@godq!9xy| zAPn#d!y&@=v{L5(-Q{p09n!>*0#=h9F_upbZ6-X@G-GtKhB)$NMy|hbE_aeL5;7m5 zX19uhLjnB12S#Q5{l~8a_io~@w!0pLPWiEHkN@WGV@N~5l!ei+Bq{P$#6%=8q6a}P zC>DOORwM-mA|~l+peXn`OT$MZ_^2qtm(7)0P92xj$eJebx>4?A7hJ*5dL=f>f`}z| z9UILFPK1JF_fJ+P@{sC&#H(I~o%6}gj`yPFf~^x#ZWq=Z@xJUDA#fb^5x#w+V?r8P z?q8M{FY0Uf;Fs0i6n;mF98v&X?!B8m`e}=xeGMbP(Xn;RU3*aFo)NEuI&NR-syNNk zQ`SzP8Au)xS^u9lv=3c!byY4c2ns2TzgN)m`UxUneyb~Y^{e-g7g7r6_J*`@Orb0i z1r0~2gmRTzzWd1^`5r&}13$#d`C4D-lV@M{bj+Ausu@8x-C{8Tp%^2E^0nC3_{GZk zL?A4!2nAHUoJm{20wb8CfjH^1Gm9-x3K%Sz0b5x6VyTxOx#PmssZ_TPjgnn)^(^i% z`|R9A;Vt-gt36GYhWS{eT&TIG`iVV%rE_ZK#p$4&Fb$>3RC`9?z(}6J-)oN%g46su`>;NcU%7= z4_G|OtHPZbR@$nb%{ugVkzYo3ev z7UCFGcM5enhK}-`Efj{i5XYvz)tU25-BcDn%^Q-7)K5pnbBAmm2=P=4TX~k}trr?x z?)s%ErR~*2_3*>by8j;f9f>aBe9|EMAHa0I44@{-N?IVp!6AMJq!&KZ#LYRV*M^W@kv4aCsR&a>LoPcMCCT|FA~;f9lEowxV(8zQW?5 z@ouZ;Ha_X`OgM(xqvtuKWf-3?wmI;EY$)Poakeyf zNhYvAA+o$wj!uz*I8~P5WzE5045Up9)vp_*@zAR6^Dq-Pw1r~uixXjzfL^4uPE#!R zZeyLWp;Ri*@f)`LqGUM(D9*A3`X{PA8X6bx4IX$|}rOy=%H9qEFK?9ooi zC!#RVD(tUI62YIGK#m48z#R9e&vRK~x*f;B^R=zR?s$9bTE@?W8Eh_H+{p0~Zr5u5 z-pQW9ls$54_|2`!Y>r+Sa5|!RONTV9s3WSG54ye}#!M(yQ0n{$YVO|0^FfO~r@TDn zh)qkMK^G|u>I;Bc?_T0NUM-tgw{4KTp7`A)%f0EVJr|cmoDGp->}8C%T#cM7Hj}QP zN*z#Z*w@0O(AN>gicZL_qhW%6Py73RAxx{Rm*qP?Wv%Pa50l>BMk%4h2|&#%ZMZvL z2lNKUiba_-SEPZxO-C=HzMM&^WvVgp;0BMLx zg&fLp_(nyFo`1Yu1g_W+j{?%YEYLK_C{f6n+puyE+3hh~)2GBeC5zn4Tw3KS+p8B> zW8#OiW8XJ9kUSsv-)WyQGWx=yj4sA9wjYgM!Fy0<9p&C5tj0!UT7!W^ZGK3hs!1S^ zQbT(~4Zyv&4wD2@j*5)Imjm)_{IzWXFf|o9hBRRi_H(*u^c=`x3$7ZWk(ve*@%H$+ zo=aGk@o8b4{(5wzm>9ETOHqenVr$w4FjWDUq?(~RfP+6>&hrpk>pJ&rAs+n6me5aL z+sobO_*knu4^qqP9AsL_A@GF?a5>>vMdlWPwE|y`QF|ky_$^KG8B;&1h&G&&yVf zXm9h1d}MCob)&-HXHs9jl*yQw%7L$^4~1*xOxN3H8FCO(;S#y_!xtX#Kvm&;_KW6PZ2%;a#2eD=%T z*mq3@^jnc!@t#`@#+)Pz#Qki47+~mUZ{X^TleQucwgr<*+>=KFLwBeE?Q6HS zPh-R_Wf$<&r!8-^rd$bMEHg?(ITuHj%gVd)C-DuXXq53FlWwNp-peUj%Y8;~D@@6B zbt&m}?w=MB5c4`g_6>awtvAZ(b1~$sKd`p;wXy@>sW)1)muD#Y#rae&AMf3(?uqE5 z&|U%ZM)?c;E99ySk+QX9#kCaig7_c3*-Ra_Ts7Bw&M3;rbQUdWvQs38!}75c0bA)) z_-~xWJMiHRycy4DRQ1oW!^9u447wlkO_8Bkk+~mYB4{WJm;AsAnRDM(SoLWO5;@U1 zb9FURzu1npgKc>o-GL+E;^y_~^Im(Zn2U0sxc7y|)a6sG6rz?BC=Oo4`t6Q(;Qv|8 z9u2CVvz|i~SXAficV0-j-Ew!T(3thI2cp-^G47+-1wf{XC}UQr2|#j#bO{KCSaNr;U^RDdc5%!rz_ zFhxW!WZ)6iOENT2zR!N)XvdjjhVZg z9QTxf5u_o#eaS}!+m4%v`oi}Z=}WT0tIPey$m#Uy&mqyKesE*b8Pm_m zSYxMCA0!X*fqtQmktgc7}QPjUy%z+H$&Q5gc8NQ#h}k6?*@{08WS4=yJ|``)*kiy*)rPXvH?MdOhs8da_v zAJzB7)J(@OKJ}O0a20-)WYsgM(1jA@L#2&uky!WzUO=o4p%PF9N(^N0NK=0^3Cr;B z(NZhx*I;IYe+y4?RWd2g@h{W^@&|TA*rn5v7yMu2R4qRzr*<%{c_8adujp7O`pOHN zcq4nW7H92se!*Kb)4>17!#jANlM%=f6`c*Cj43=eOQM0(7K(~|AO7yF(P{uI4I??C zD)cN(BntQ?gFNV&1FFdTRED6QGTy38w-6bs-t`$fxtJU1rK42chk8WdZI!Fcyas6C zB(+zVh3h|VkajV4iDg-ueeVDsi74E~e!-kw`{hC_)Z%$z7n~@0&PbJCQz1|*HH@_@ zEcfA|;)=CQ-xkJ`oMP2+^`YAMrNWSQiKI6tq>juWi)31y`NBVzNSzmt=2$M5S2^+K zqei_1g1%pl_s&Q{{OjyWbzkqpU$T7NO~$K4D5+dnE=&fA;Wh|X>FLj^N7PzxJhY1{ zLc-is?+-5KQ87Ol``gtYsKT-vi=+OU9gXi9r!OnL8SlC(Qf1({!bhQ=8MNJkP|Ll4 z%eP_}u~nyiqW5`ceVY3$jZQF1NLxNO&8hn=5hDz$^(DP4u`%hpwTTV`;0u}m(BJ3t z1OurzZ^*$qF=2w){b+W!w2}iY>=66;E@ZT(tYSay$j%M(U zRr^_VBazdST`g(tZDVt?Gy4G9Dm4;glP*mZ`}^2?y1pq#CvWPy-NfArY%BT8>*% zVW2p&O^QkfAcA;AxU+g)cX^n6um1M;l+8D|%NIwq*?|{jfl8Y@2j#@ebeAyZs;Zv+ zNqGI>Q#bY?mMiKyt9Q1&Yo9GvO1b6WM4!A#ExUueyBgu7hBN@+E&!wJScZGsigo9u z>(-2`)0aZ2xc5OS5-lbde6!7UouGKsD0bF(wvU?hHCJ}Ll+ zT_WgeeAFey6LBSxAUiZ2vvDXpMkD>t&Dt%oBw zt?j_})|QBX5zym8U-vFYsvVP`UtrxD*L+d}FVSV8o@MKuB4+YHT<@&&$e%V+hg2gN z+R^wo(x*&C&alq^_o6|8I(Eg4g)4LHsNW&rI*p1kU8Sx9=z4)|i|2-mQM9`Rr3-_<*sg`K9t?<9*xkN|8TXL1rPk|CWpZ~6O5jqt z(%v=ZljR}Y&NMw?&ej5+ zRynDdC1=u9j>aBmn__Wg&aZB04{PJsr>TyUK4;?2xDG2QS&%Z0l?k~MPw<%V3Z6D0 zGR}DX?qMTze)d2XG)~z+9COqMrt{Oqd|u@cL@awATV2%BhbvnL2S_>Byud%h?sQ-`|rL`cxhva71Vy_4qy&Tk6#V16wbl3w!c zXP|q^rA8;0Kh$9Hr(~k}TIxnK+cuDyD_z_)DQ^4Fh5_EW?@B%v`ZV{(FrOQ4tS_xO zLk4V5;!&pb(83%u+CztB@epiHiye7{H>71nmi~h5wD89FjPN=J?eYX#RUZzDl$YN2 zwI(M88=>9uFG=qu(iEklv>U=ukTq`6>$ikpCw$kVV6k5?aOYTUoM~03-};R+7ZYrV zq6ydeXj28Esl*25X|zV4hEkIpRPXR|^uSyR_qeeSm=NSzk${Wzt`Obw9wP$DX#353=Ot_k|bn zl<+(-p6a{0-)d)gI2Fz*`4W&KkYKaQwJL{d)5@x0M{&~;?w7oR%$KU@9v>%rnO*51 zrtaTi1l${MeZt6S@)E!AQbs9NMy5C0Zi}! z2qS4b<6UGWNPx?x-ybk8<-aEBg z*rvFO8@u`Xywg4OhrX?9!4P6HND`t!Q(R$!EltQMcS2P6O&I+oMQO|HeZrxi@AfJV zY}l>(7+mE#R~PUm{$&wgzhCQ+zax~F**JpfugfNjZb5e0G#7cB=hXh6*hl;v5C6z_ zYlZ@YDYKjeqBte5-jhl~zXhVkj@iU1;pwGPYD7URsxnK4K0PAgwc>5vP@wjrXe7U| zY0=mzXuNY9hMj7Apj`WQZpX*+%p%H}o-FGE*|(5(1na)h^^z-MjP^)hy8gTL8&w;@ z7gcL=5iNw3wFJE{xrY0yROW6@;~y9xCDd88h!nm<-X{Yv6997>3t3BVmIY_7-|VU5 zRso~69!hJj%tw34!}{ReSVBZ+4o{&TyyOJM0(fGdHfKH-KE*02?>O}wNUI_gFyQKB z)X0w-XELDyoRm$&u&j8W-NHy|Q11qpi{(?<@7e1p@2b)}t}ZW(u5;4pfYv)+d*|;? zRzZCf)e07uIZsj#0=QNktSnCsd4BmYAGtTul@cMAEEu~wyPZZYQft~ZhU zM~=PB6!(|v2OF*_T;|oqMG?b3`7_$yHBCVeQT>J0fBgEf zmroR;=tjeu9_G8qquP#&A0|KF{h@d$>-=R2PXrVybO9FdB-&8sTkLWsa)_OL2fx9K z=f2+YGGi9}bS%V5Of3cjj?Sk|&aWMt z!%v1U=jIvQA^i)&i=xfWUSpy7=GG0tAqng%my@QUT zzdcLf>1ut-g6?$Ev)%J9f5xg5_yl+Bfu^SR4$4%m7Y3$A2cG%rPB>n;@6=*9Ft}KH zlN8T^gViJH-jK0k__5v!Ur&6~DM|R+-Z;Q>%GEybz_&LSRsZ^brx3tuM(4UD?#W)F zaOD0Q+6$UakclmoTd*AxU#;?3;?w?KyNT@Ks|(4J;lDxLeL^qRvwgi#2H!_=oM5_a zj@JxEJlWu3=YAAL&px70dlp=$GBw^MeJJGRRuZEPn$~2IzrJ%=Ydp6fEw%iKkPdLo zM9uWT8E*Dr-%IDb-#aK^22SdflLG|72^-iHg)f8GTt{FvAa&89mT=}!-PBWkhrH`N z7Tsh{(bP_NR}y`eVd}c@ElAD3J=8C|Oma${Ei#OQ<&7NnXBKqKV_)$Z{p9)1$w*`< z7`7OWVx8$V&zpi#yawS6sXyJ(cvgE8$f>67l)WjDcwMzLA@uRCWT-_l*{mfd)>Mhe z7%~Dt>qwi4{xbIhyeLw64i^oDVLa@SD|IAT^Ek_!kBuPO&aDZk??yMxmIW9rNXVn{ z1rR(>#-e=nPsz!`b9Aj_AQgYb;I?7vHgv(vxVkJ)#4z;JclIXC#P}k`cG!$ZUI2sG zb+;uVHAdrD&yvVwf5UMu5t(ex>N%zx@jQ+2f#E154h@uC>3B80=v-7`;?fK%O8)(P zc+NHcwygT?Z$)aVZRAA#VDMlU_qa}Sm^ShNo7bGK1DS}`8&JFXA_Qam6!B^5GJDxQ?wlRIg2y!a3)=*SK6Fdi)G z4`uvjR$D3tQci{F;;~(nAwoCoCR)B@9`jeVkEQs`4HMbJGAIJE`Onjj1+TW zO}2KA7x%pr{=!pn$1cYakES26AHQ{YDKX%;!?P}z zz!D3>9>*w{&PY`_8;fpP)H21h3x2n=#`TR0LqhPYU#D-k`2PCT(;aOg4ix`o^+2Jc zZ737Q>JQ{1ZPA$c>hH18$4^fs_`;aOh)%T%BZ=V7Le)K%6MQ4|wuyHF zo#-XO>am&m(0cIlVmBTxsld+)$ccgcAJ8zY(1E!OAbfVSnaj?Hc{oM_3r9%*HMBwNe3^z$;2 zj1QsBPO$M?u@{|&I$Avi!ALFfZ1T2b4{Hxf49%%EN4DQ9Z537hR%b!@i$n^ccAn0EzP!<)>WC(QWe|ZIfXp2 zkfRGWq4@O|?QQqB>f6CpPS@P9;cSpEk{`y-Iu-Tjt&!$6Ch^nbQB1i@K^DF*USr>4 z?Wrq~@Nxp5YLD68kDsihNAs>{QcTA1N*~%E6^IYRHwow2eQI+( z9d6)riX9HpQxfmm5~lMCoAL*lBi{|kUlYhtO6stBmSlczz0hqfcv_QQ50a~9TJFAF zH||@OkXye06BZTpmF403pn9)YRxTKTqajF4#(zHEF@C8IG%CGPg{Po)6I**(jKfDq z3K;i?HI{IoFC9VUROjf5`516#hB{cK0M-zyHS; zZuCN>FT?|Ni!&!z4tHyFB090jXjfV5J?=aImbki`PNyI;nwMzg@Ooj-UmU9RRIti| zhIB12(XLG1kRfn}>AF}zV_yp^+#&6)IdE=u$4pA2d^3mZj*w&(zM6%PNhu?unnm(a zSmo^j!dPOl%v-0P_C9+Q6s_wc>%v+tk7SQ$Ta?RI_oQLM9K)q+bL3q4zzMXu#uzJ2 z&`A8q#v13?brbWQn9n0iG}x#;h`Exz6RBsGA9J5kR3OCzuN4O)AtK{PHFcBS#M&De zy-La*#rNI9B8H1NxpAb1Oy9KaD~90SME1Hj>uZQ|p<=#}Ci8%!Tzi{~fngS0%}A_REYgwG%@(zzq~;R2_}H}x?N=b2K`-KDKgZU`Q{#LoXIxji$l2&;l*(J#SZ8N zg8Dy-#tV~TdWmD3XuJ>Jg!rD6;&DFivZ0`LsafJ7@zxc*>+zt3`d_|JXr_%7rdKU@ z%cJ7}=`d;{9TE$`nT0cc>AGE-hKdqb1#Zle3e-3MAwbx4>FZ}4;w0m33X|8%Sa9aH z;~512ZQV$L?zPLw>&gX$DF>w_4}r7gFfqvrOIq{2PDc940Wu4_bT0m!ZHvFK^rG~; z;E7Sa3xlAWeBdvefdT>lw)UmxUsJaZIhWMpyLFgIOdwncs9%9>wOCv734ULnOaO)v z09fLX56>N=*J>$gjQF3iG!xNe%6x6VW^8C z)@2;kVY~`g;u|w3uk|K}llB(-`|JzXlc+|t#L8>C$%*83%kdgM(Tt%{PyuycdtySb zi-Vm#9P7=Y9v2dqPc%V(fRHMidm8X%2E0>ac1*3B9=~$~53a5z zghmov&GqNTr*8|~P4$C}Qygs0db++t+Sp)SJCt-Z=c~U*%lqc?>eR5JFBz|Y!SANa zYdc2d$bI@BbT9Ezs!tr;I0_j%c!BHG-SZc%S(1a<#i);o#o2Z5|8+{r{rp&%G&ir~~r=7Su7e z<;?Q-c7;b9hS2%my$4(Vfxzz-^%W+9<5l(S3U`6+O()-gMhg-`Y0m6%*rFlIU)k5G5E zhRBE02vg(0SXv70DoN$Pv06&=DQ#*pJ1-y*2Mf~BcWqwQLmb+$Tl;9gJvHpHiuQ)1 zPOsnmz`@UlqMXhXaX&nj9O&*=*KGm8!WS>NAmv`iS7;JB4tnM@)d87t z1uxmLO+%U22mq`mmo|6r3_Fvt6?&E=Vub&jEFWPpx&8n^kJH8}VDlIS4UR;&9d%70-x1oFg z1cC_?gr1`M7e)gj8BO#S5%Lxfh4^no`G-{I&Mz8n89DTNJuTo0SJ2Zm&Z{Vjy(~}Q z@9k)uaj*^WzBUTZX(xLrzI<#^=~EbRUS;<>vkZoDtdYyG7{+quIH*V9+zbZnsNjc19d8JNi48V(y&I9Xj;u%LL#)X$?s3Az1tR>OpV5!j7*#}pn6 z=sc6TT*z5-!FCc9qg56Ml1rHlWtHd6uXUQq)-relkr%L9F*3mESX4%&1gA{UOVcFj zVj(+Zw;R@a%%99+uMxq)Nyuh@vSOX zxJ>FaODSfHCt#xniN<~0Iu`<|(5ev={~0meY-&UH(F$e^T{$$S)@!L@ftkL;`; zCVk)hO-f98;4%lLzaz1UJlz8*TMwhn+}&eS6POl#oDV&rWRC_VvtKl`t9dTy*~0_} zs@F;sb)FM25BVW#+`Bls!Pu212_6!1h~^-S@tz0_U?lL(-^3e?gYS)eW`|B3V8H4O zr`^j_EvhW+GP>e5qFF9g;N1XOK&HPoCv&2JC4_lRQOq&ZkTV(?RE)4DjuHSwbh7`( zBREPqCUrz!5zud37_tmBH}ob*-veEi6S{`?yERSYPu7J>?r=$-=M%B4+2M3O;?KT~ zHG4X)_LVI0rD2XXQkQ80E?)6hAe$3R`tKi&9l%DhvyTb5^{ zIx;Ok*;|wRg{=g-MXQM+P5AXcH?zf0Y9=S`7u3@nCoNXZXcOa5*Tb7#9gjW-?et`x zOF=X4{{lku{}F_?W;D?-_+GV~z>NlwM8*ILh6y1;%ZLU%iun4e3mAb<*@@^zhDJ3R zy$j=2&J+acKW&7v5By1>WOH3qXbct$QhP#NQ_N>T8*H=LpWhPTh2*^BckGPqPNiI3 zN&1&<{ReQWJA22j5+G&y5x**Pr4j{O|A9KOtZwVAoFWF$tw8=|tCo%F;$ic1#$*;T zAeUgh8c5n|dP0#zF6SJ9W&g6jVf7Yr25n=kZGVIu6bLT=+O)ngGXXVlE=8f|K~^a@ zT296Iu55xR;Ed=jcbX8L0~jQPThFP`qgw?20C8Wu!uF~yrhOh3@9|O-C=na3Ms|n;h}x_w zLnhHy=ObIF1)ms>E*O{ z8*AuRaZUq=&N3}ha6nyN=LtuEer)#2OrtB1tN_^kqD6^R9)4Ve-D*QB;S+@r--+YJ zo8q{L4%CvZ?U|SMqzMU}rHKAuIwglJh&6~4t+7BQhk2x|jyJPQW zp`H7XSh6OU4w9gOOd<1dDk(;;aJm*^UK)&Dw!IXEnqbac!LO)f$gMNfi^-17^dQ@4 zoCw4Nh8KcF;quK;8+V6NR(_DXuy%EC9a6Z6bl^0~$HzpJo|73nf{I+x$on)oM-g6& zy=9@mDo1E2kCA{KY{W!T`v+2w#%?K$#$N$<;Rbp5a#pB71dNuMwDJ$HZMNI(E{d70 zuXI%!>S~ld?d&|CVQLP+v*%C@m)kn|q+88X1yZYB9z*_MZ!rW&U(@M-tQ68B}ON}g=ror~V&dwuC1hii}DpAX4cblsMOf+n;$N`7$ zLK&r`&Q0;*qI5EZ^tzW!R0xa+gd-C`ADBV;5b!YHDlh`mnc~$QXm%SK&WW&4YOvkM zuWad!W{G`BQH4nRWw@HtB_IWyR4GA?DdTbK5gHys`2g7=c(Q;!3y0$3Dq1hr%6q8& zdyy0x78IxlWG-wxLxn&Iio3IUn4J1=5!-tA@j4?;VCY?VUv*Gy4v=FK<@9gC3V=ZM zjXGac>>J<^BDDkG0}$oti0U1UE~t{>%EWOA?UWewlJX9R*x*I~v+UUFwGZ5%iYoi`LBEa?DB!h#cTqR;meT+j^|6~L7OemIVW6Kw@0o9S+V;yRWF?tW zxD-cs&9;9%JrI6WapfKI%h3|DjGj8-!!kt#_6z9{9657_ya{nM{0AEX=}P29jrgx^X~L(WjrA4p$OD)a^rOU(d}CwkES4!YvH`J zJRkGbLyvow%4;g&OA5nmQ?pF3bX~C!tGaOd!kCe8vlC&&<~dm+@e#?@dJ?zXK6cei ze%k}v8jVRuP2aX5MaH6QAt)Z1r^qP2Z5EVIt!gM+F)?{sNrShHj;%iq}dDNqCF!Ip)Iib^KM&OdvpF9laJ1O zhjN+M4lSu+zYZQBtf%EcQu!m0JAZ|o+v1F!RA|ZyZoyrZhlyn0o~n+ht})xXb^8xx za|zZGuwD^%wou}J$6|Um(^l~D+Z^dA!-0S=)Dqu9RP_-TlPnE$VxzsV3uGxq`(2;A zorEVop)X%qcM(#T8E@dZf3CbyINU@aBCgs}MN|v0z#IKA!gMT3H2x_v6e%ipdiReY zt|VxIXT`E$0J7>aZCAB?eQ&F!*_7EGWwxZFn5ABsJe!7;Tte|h8^Px3)E%G@O!lxU zn2}#!JVaX2&8qx~psN#Ejgyx}@f29JSvNg5Z&XO`2Y=n?Z2qHj(tn@+Q+&15w4tsm z1rxf5A3s7Sdb05mFIYHJ>}RpQudDv?*E1Jd5yay#rx2!kE)jAzvHe>dZiZ4Z7x^av zlrmsNl-?^9sci?DC#Or@Vu^jBlM{YlB?j*~3D6T1X=Z{?NvH;;07fL=3ts)T&p*GN zuaw13&-^xZ_CIdKZ&)h<8n+dE`ien)AQYW zVPZY_0|Rz31&hJ)2LC|c44})$w{Q*H2;K+G^XJ@kGqHo0|D@bv$FOAPd?SO5)YaVj zGl$1IR?^AaCePY<>|Fp@?chEiT?Q+lZ9=cM!}VuuAKyKB?*{xJxPvftxK++lz_bPE zMX*?Lnp~5)9Ad}pdnhUCD8GgRKp*56nQ&{vIOvpIrNp||z7G<4TQwcdhjo$KvG)E8 zJ4pBWes@y2xl*zOkQCq<+rI`dQ;H_42+ z>jeVBXnwzNGnj)i?grA(;=Su(#R;^{V@#mco~8~?&86ISCYpJwrMOP zwLS!PcNv4VO^*yUyCe+!2zWYVVlivt?k^I@OS2Fj?V#OVXla;&*b{rZcpBX>&}1mm z4c7?mLV^gzL@nu1D@2ngF3(EvdIu)m5>y_*r_-lSxvfe`xfZQW^)4iasXJ`N;@QbD zQVUlq-6V?aYurlsXz8tDLcq{CEnmXtv)=-3&3gTM0C2byuEsz$Js9Y9^KhlQODh`L zdRX*5rn-o6dnT75tZi_PTfJTZ8#O1?Bs@7zu|{1e-b zD`v(L!aX>Olr6Rts^^8eAbeq}2+&$o-&?v}h4#lyED)A~?Fz-jRl9OD)ax+$ZHCLw_*Zr-{o@^`Fxz&1N>1O4}CcH+nA|@8nWXlwXLS7?Fz5i>Vp%7E16pc|kHS zXs2ni1;L60Nn<5ebxq0@B>Z*!Lh;>t9(@d4VkdH7jD$@lIjns#S&BhLLQ>6SpmifO zLV=vFbF@GQNVYL-is1)*e!vsczokBZ7M@h!dtoRZ2ITNRnWmK&SiWF44Hpt$ZAV{d zb0w=_;pC9?JXYMl^CMQethK)5e!=M!1b>j_e!X9XM~8t~Yc%(?(|g}_!|i(Ci<#s< z&TAxii~FD7l!GbvD-YtQv0C*H!s%=TV`(T57~^@(7GzoB?0i1r3~Rb+#3+r$^l&Vx zD+8c1tzd3YZWa;s@ktq?W2j?~5d%pHWsL+#)%3_WwrM&|$qP=ZCN7S4kQH#Pc3}?d z7@C+Wfo^*7B+Q^_*U6rBGNECcvtBxc4Q$Weqz?{fHN<;G60D*0=F?CD*V3tAEzf}b zzXotK1qu_w|4KfLg9WJVtGnwNR>otJ z6dRSLF;yKKC%`h`eNk>R7F@9^F`IpJA&&Mxfz}Fw7HF8r@&2z8h-spfW7`SPEh{#b zOQtL&9VHU&la%SqP9shvh}0YL&+cIirbwd4BJs~3{uIqr3Mr+R5HX(+3cn|v5=g(< z_ze^Or{K!&_tDISR>%Q=wZ1 zMW|w*mq2MA*3X(=m#4kSjt|DyODI9&K$L@?4a$*PDSX8ggPi#!Z7j{| zxKwDEYQK%N;0h7?b;FCQ9QJXS6(H^$%{kBonNW>-de zCWx~u{|OLTxsX{ysl@7XI2eE-=%s_;vp-^283?1RYeK2K7w2VXal`V{AXFZ}ctJF9 zI(>R9GnIXReB_jMYGiz$(5BHJ(rO0f9X9&Pm%p1rJ74qJu~-!p1W-}W)-Fn8Cw2Qo zRpKS(HXGxpuBm34I=G=B+UE!Rd7gFhbqrHZQM5Tfr(Wug<~ih?^=3!o|HeUt6t(tm zj$<#7SGS%W+_oP%v|%i89%x|;_HgPNCH-nGzD$4!h{)Jk>-0zAWp_FxSx)uWZQ~KaS z51iQ>dq3HWGW{i*Z(|8IAp7 za({#I!T8m#@$CAL`a?%zucR##RAc?&<3`*~fw+_AX-76wB1vQrGQ#^Ere|k>o(eVl zIcyQ+K$M>vb4Jr-V*D2l+?_UK_IO!$>Q0sL{SYYqa|dF|HefXn`)+rTV`I=+`g^ir6 zeWVtVH^vzo8J=ZbI6kaT5I^O4w!yQ6RS{LwB0pny+}*n43#^Z)Zh+Gse){o}&1dSa z&#a^aMfOvcxTD!8xLF|sIQF%H>-H_005 z0mB7={Xw-=3{6wS-AhFhVn~w?he6rRaGMah|Sa@Vm9>oNqiIb;quQ3$xrN52*G`RU22OJ zVjtUCqf;giNWe6St)Vcs&USZ?CU}R&LcQyFr6e(m(SSBdD>+}zpZ%)@GNDVn{zT=( z{7pIZ+pXv;R|x&PmmjngOYoMa!PTtTGoZdr8*)%$umE~YAcq`or*m>!EaJWOZQqyO zL$$~UK4a2`YK_Swx}wyD6tQ=_ARm>h6aQV|joeU$DI%(MQ)^7nN%%E%Nw{ZMAcm|# zfc{K|(xFZgw%^u{pcPaz^U|z!c%PSpc4%8dYY8XbmQF?tdkvYOH|QqZpDt{Vfd3oG z-U-`l+qZet?CgqLBi+hY?f^r`fUi_!1$kRhO5pY=Ty2uW;!H5CRGHr5KA7o@F#@mT zY3+v`*jWOwn?|KhL7RxPle()T?MDAPtL#rkk)X1Vsnf2*W6OPQMao5&QMsn$V`h$vkT=H__Uw}6H2So#X&FrV>gm{O zJ5^gSpGodf>-&5Ha~#Mv&@@{XQWozdu9YE)2&-e@HQARCVti_dA$)&3)(V7on=n_z zuS|e-p%FU7AVIiSQUgw|OmSs6JeuPW136|H82zDiU;}Y5_EgJAuiwMFBnGD&AL3-O zK}HmVGc`Ke&qN{zmy?!Y@bTls2vE@QcYlY~;myjIWg5!liX2T5UWEB1JU?dgIkZ+{ zN&oIA7E+RBFR2|9dqetM5PYR14!?skdb{V)>n25K?JCAlQ5qKyLK{aYiZ!@+`OFQM z(gyw}@Ps()#Hg`bI=!u`DUh+YJO%+&jM*&_2rS-JjRTPZ4so$<_hX}HT~Hi-dgboa z$3%;Y^*Jd}RtoF7f>J8EXVJuFIOOgm1l$~cx&uM9bF850@M@PDshx;GM`yfK`4Nxr zWQUUa_Ddr(vwZ(em8rUx6Xr-#ri_$ogu4Yyz)hbY4u4Z08o;0lWqNh9;>AqV*IMN# z7+*HUzbNlBVum(EE|Ho!lJVWu)_CT6zEEEPqg9oCL@8|#qj#D%esjw+)||GM{*CAJ zS>F-WW%CYNI>V8l3v?RTWeE>XG&_kT8?3!@DNhb3dtVd%2*WZ{SKg4B8W;~9N~ZTZ z8DFpSrA?)E9z!Z7_%P)W!DHNm1XHK#ZjMH%z#AZFuHK3yT9X=S(dX2Ju6YFsNhS4-5#Z=9H4}{kF7#B1b}R@Gxi>0n-(vY#x#T)>*MpS z`w+=JVOm6$@4>t*S2yyaQYXE|`&kOz#08yHxKt3GG>HVwxP14|3HQ%x(JLhGJkY7j zJDQ!<_1UZ*lT;3z$z{ukEoQ@idsOG;Hk?w|XDL0>tI7oUa%b?^So1k4h(>81mm1AOp zMyHNP9_1dS5S0KngQpIZXOu|MzgvCj5^tD}+ns4isxwH^J|`o-5h^_mOg)LCECoB%}^RPaEwD8nyn9kc{= z3+fRpondzgAn@Z(xu??Y+nW04^o8u0?rAS1ZsTT>?5dgTgM!YtyE*ekd8+6xbO z6UpLImaP?pmew}u)m~#kQU|rQ41w7hU2;>qS|yf*4`O76O)b3-QLG|10GU+x2y(UV zVNuR=Sc)O_e(H+rt7lI{1*94dg+jiX4YJQl(=qE(!^ z+nUb)^I8RYK%kS@=G&n98p3taI09qZKC z6L_6nsX&W1n!Yx9)m(be*;te}xH`$v=6daevN$@q;Ag7pyw1*E9%U7@yDF zmUtFz`9z6v;+Jm+esaVX=#0PXIN|as>r`_l-DmU-hN!@azR{>Nr2PmDtw!}5`6SCm zp-&VhO0+PQVph-|A$9j?OJV`Wp*2fkdJRm`6!L-8IGKpW*}b(cp$Oq>ZiMQ?MN7Q2 z@pDcUc$3siw>LC!N>86TlQz@o6M5isNIwAN7tK1GtqExYg6`H?LhfhbjQ9ec5hJ5t zw*$@L9mX|tri%?RmiD|?GeX0XXalvB5I58pEE-%@$sX{B*;5u-QO7FZ)fHuvpz#I6Y z@7CJ0{^|5!pV&G$tq774K?-k3fYX47`H{0CS@Eb-^?;)B^1twIqF!4?*_`{&bZqu2 z1wRcibo)M-wJ0+5>$^W~CByBY50x{qklL!r>2HoqAkp;d!mHd(@?8n|q>5O`EQ zW!ek0$j)AN(s>81v8qBF5m*Ge?(se+95oxPlv`~eJ?{0@@eS?1QPa-)pPJJwSBjQ9 z_L{aPo$*!ohWE?4_24P$y1RL#mFK5K=%RDbvCvpiXiK|WNceiwMlG;J6mfDe?2FRi*I+NH4&$@ z5<=#-k}F}jqGiOVWK&f-`!``&IA~Q+t0;ju1W+OJFi94tP3!W&^ja*wLX@IM8Fz!* z{HdS@CQ2|+G`MZMcKrkXO?B<803qW-q<7>RNzPkFXxM7&8FRw*KWL(;mPB(yrg`6# zu`6KVesAJH*a`UpFjD8j5fl)z|;GqMPC2C zVcA zW1U_~_Y2F_Xl$^5FlLUNwvG>3T)cOIz&LjRTNJ!%Z1ejzv95OCcy4@LDQ{n1U7nPv zEH|#9GL66&4f!!^|IV#K3w}%IIFYq1h0-t07m5zzr8t2lb8Fd#@J&T_?ftXkW07iY zOtAO_t_Klh7x~gLw{Bm9^8Q+$K_S%ZD8(+y>h)pcXtSnB{YkVtLYXMK6vbGj3Vgc^ z0#AgCs)O6REgF~NU|hoBebDdw*3iWwwyosi(%wW)1h_RPJwxnKvF`&aGcbYbnq;6q zfnS>M0b@)5aUjws3Pu#lAbX?kVCMG2kg5dzEkUpI!8iP|f-#PPK>X-F&InPCZJ5!# zyM?{#HX;&Vf+D<|Jg}Jl?u;b`m$|A{)}mcbr?VA#Ou_%m&PESgn;v6)NWwU?e{GD5qEV9RU~E*H{MpAjwvGnZPlF43uim558WZp|DuzP&SWxI)=9haBo+< zqyTh!se+Bt?KO3+% z09JhswRF?))>o2ujRMCKkB`;al8doXy7e-RKhHGw)}Ac8+vEALI5zcUKWc4)3`W=x z_iN~e#X&+y)=UC2fWshpVMf0@r&CScGL#AOWQv?Agxo{J>o2=G9C=f36EOljOIYCX zJfMjz8$^XP9hUkVO`vpO5`eY@T9YC05$kDWC`i%^0K$q+00l#Ykg+B*sdJy^HR4$H zc)|(88;vbuUp;t9Zl!Q!UQVd4xDSb5*G|o>>-qNGmKV(9- z_JqCZcsG+Ad{xs9w^VK(cth|;9<|=D?@%&%EU0W;NV`z}o!|2v8I({(<2Cf?0iu4) z$HWjvM)#;c&#cQFI+2^9ppjE9i3&+GdXsR*t-7&y&Zb3BbU%GdhXwh%w8tt_Zalp)-03 z=p~oDPpr9N96U8mG}Vm5fQkZe@(=(?PJ2C{0xL4iG$5?kM~2`x?G&BPzxf(vCY32= z?qC&KNG(=MjK?5pe54Xq0%@H8*qz3i1v-rOtl`o-8(W{QnEh~$F$A7^9*rGmZ`|)C zeS#~7?oiDaat>6r$bsfnKi39b+Qe@|ZfHGNHCT0_T*2d^2@{wA}<@WoIU=W%E_;8WwL9pCSmBJ*RyAyKyJhy3)6>OU4j2)h0`u zI?0wEN@rN`hg5l=BZG%u&M9gtVZ(|$+E5wlHMwlh>qcBjRQY8bh@;9UQs(hZj>Ryo zL}>M>SBYXX9a$m`%btnt+*ykL^NNLqx$L`!*Qb)IzlRG3^n4-uKL;ETQtiDw#M7#E zHLlsB0lEo#MBy$$_#onouQ&dT#QLCA4e&snvZ}NUfb+=5n2)HPJw957M;{ zGtXoH$f%ELh@#H8uA!zsV$3-`EmAB>fo|%e+v39UxM@sD#Q?x|Z?#@5#Q+bQlxadw zT#-PK(?BUPPeBsV%o@N?Bg-^O?*jHFo+?9JN=*Ra4V2raEYw%@=2mI;x9U>ChK1Ej z?4il69zwYGa(HtSuUSls>hu3OnF?oi!Z83!QK8)c@_3Jyqz^Y;ji5{<^BSe$KG+8t>1wdz` z(SKUtu_jE##a%*a1Hr@w1K?eEHtG#9&H^<=su&s_rslT|aH82W)5w8JsBX|$wDA?n zaiy*9PNsIF@uOIN_D1V~9rm_pIP0NkuRc)mwJ8fi(M7^!!dEV$5$yr+^+t%fQN03)qCCfZ`o+Wnzo9Za=i}ps2z2%y|QJ2ceRbII~bF`~* zS2noBUln5o_p>2=#p=&U$fZ(f)5R<#QpNcddK$YG1lm2gLnQ~*#+i?VqH+&SA^I^3 z4T{K69%uRvw;0uYG$O-zTcF##lcFYHFOXkbIy>U+?QyLmH)yXqq@U>Tjz*640N^Lr z^8}ABamT1pw6#X??7BP47UFMx)4o3KPbd!b?yaGPoBeH6=;CLgd3QFCo)QnTWtEv% z7@nvW**$bwlW$hrnT>FP9^W9{j~jh;TfVr$QLzN-*3j6aX>qn4Y2|yx5)sdC{JPWg zfodf^nd&TlS>*LicY+VoEwY|f-Ba`C>_u$F0P2(7lzUc@F4C)&KPmcFw%(t?1{ggE z9u=MnuZL+B8kq+DKO5?+Xo|LVDPcb@HF)Bs$u%(XvrlAuSEz@Z74_#DW3V?w;bR`tP$)xB#=3aOG0vKReKUz5~_J_3t&G0GiU`N zdmWutoj;*kx;>T4EusVcnCVnjcz5z$*9SVrW@CPz&+m5GpO!Ph&yJ?dU*VKD5cJ~i1xmI?e7rzo=fmE7z)a&f70ZC2rq3*kSuJl_%`TEO zRWy60AzzTx=AyGN-bEeSjLsM@0}Ug)LcoXEA{cj;Sio0AcmX_~vtH|gKMa|Avd5@O zph;|~eC2wt|7h&s)|Z8OwIm$1blp-_N<|ZDP)tA24uJWEkyRO)S&r=DX%=>V2?;5} zz7!|5M<{kYXI#NW^AApiri*bkF!7@#cTD#}&0^uOrX3dac`b_{eeHIwIH>Qg2yZC) zs8Fz4gcshJC$|fM{G46m7yWDRK)%7h7`ufmQnYQ|yI-U<+}B#kPYo<$AARMstdYsi z_s|ysmQ0v^K)%-q8Qp@caY!e(^MO#%4Ypedy$HLRNIbv;$+P0jY8tb;u4$8^@}mM< z3G@$;hVAHmm_8Y;U&yLA8a8mT%72Gz1w-hUP zu0U};u7l*;at*7e6WDK{o#LSC@Gy~&Q6W*>a@gchr&HlHjzK6avUfmqMYG{t!`*mu zIkf3LU}*50gk4T?OTNBXD#U$U1myDVO~-SL884^t!%b{4}EJtS_+@5x5E>Fl&|_z)Z>72PlU&ra?6 zI21{lXLxjvm|9<58JdG5T0izbvpK|9u4$$}%L(dpnTPD@bEnp`FN3l;2U`G#?~&aK zdArz}-hnnAp4EI5*6=}OaRXd>oK;Qp$u=GpkrSM4)I#es`h4(P+QSual%`-u3SctN z8~(({-L0{U7G~}X*|HI z7~UFrb!;Fh3rf(IKF8)zXZnk*HXJVZ=5Lo=f0sTxT(5ex-hMwdI28O+Wn%6frtMgoQ|1BZ?oOIN%$`=X?l z6`;OnJVZA*;Z0AqXMykQ_i8*GE2ZKWZhW^wvFsA^g#UavG|l<7dvx7=qWO|9 zpOh_+lw)YIPuQcQS$3Gmep9g?YUvCpEmqWTbxg@uj z^uEJVudfhM^%R#?h~WE0!C4czk6{ATG^#Hl=r`trr+M0YyRu{wmes$A4_GOILRRhz zQ6Gg@MVh?H`XuY=s{3T;Z%y;>BdGGZ5zr)8Spqa;bQa?ZJ2*#S=kdr`RS&&mDm3@f zm)=SeITq-_uze$Fb9vg~pH$DonsCSyb|uK*_WXbcIwJUabUCf@`S~nH27=^zj;%Wa z%wHlV+{D=0fEqk{ z1c$+^H?6|G!J0V@R$i=kGcZ{B*(UFYr6Q1{WMs771L>78BTlj^o5o-gzN*ZX*Efb7 zk;qVt>51SuwsrJTO<|xKlM=|9-EB5SMM?QYEon6YwWlln|CwTc6J;Nc!mv&Ol$U_9 z5HU>U+O>#LJX3|@hW%Mq-i@T=Ea;HZSPJYpJ3a&do(IiVMG9EWVj;LXVmJOXFX zZ2&p#bd|Uq1?jAhIOsb2jjN0v)U!zqBL>Se-+alpmG1?u4`erSuT~nU-|MniLPxu~ zSAhRiBL~O?TG@o3)fBRb#}}B$w2&lF63D+bkkUX-14gu!q{EDYO|wV;jl=|!W6fZZ z;7&1r0h_4wIuwk^osPf|_><{Bu1(v?xRGNvYq-zjMc*R%_;<^US+8y@*`O6XafZd;Wdcm+Xn>QXgsXTr$*6`0AosL=G$&Y)|0-s$Mo=$K8_^ zbK6pQH%=FjttOmQRFzpeLAk(x2##$P#>GV+I=d{(MZV}EQ24b+_dI25-sV1mRrp^s z=6=CxcIlWClFpljHD{Mi@oPLZ^IHya41r-FngF|PpWNaWS!7?~eKv%Yd~j`K>Y`V= zRMu4&F{XA5yg(hl0Q1{~&;>^fovO{VRVoQ)R(9`FZE6pF^pyDAR)ufcE_d|TQbtF- ze^0^4?@L352TI4l*7l{bo4m7px%W>NmZQz>_o7Z`hu6rNfkLfv<3K<{7|7O`-e<}D zejX)73lHgtb(&3q92+UJ_47mvaiaK>5o|G$0Cy*(KP^h1%bEObPxb0Bq`rVkH}fb@ z!lQ+bU?-Q6Lo&Ea%?V`A$)4+!kEqICl(!L5A#Sf{{_@|dG)biB0X-zf1CX5~CZ8uW zV87vJRMIaXAKu{7{(TN`DcZoRL;X`ij&2^pLEI%~W0Ev3)wGbr(o8+Z7RVuAHB1uN z{st#4$HdpVYuEW+=heF05}s;$M6{GsPbD=VqU8GVWF22A?1)4LkxFdmvT6%O)yK#i zKf!UhVd!ScEYZIGF2IZjV2*K(noE#M9z0k1g{v0Gg5r0?>Ye*l%EI% zx$kpT7}oPMCgi-GTPBk2iEQ+9fkh{CYUIf?F5cQsFAO3#O!p53QZ4oFq42}T3oT(m zqBB1?*5f8I#Q0{NqMnVmwMrd#@*en!W{C}b1orNxVqAW((zV!qjvdS{@3@^gS`pE!A~Dsx>+E3!he$9!c`<%TK8qfj@?<^WzF9^f_!H zZop+7{IWDN?Pl^&5{*zqzj7PXI#)QLxjZW`-4 zpZ|&_9Pc^yvU<&eEuaOMulkb+Sce#qW_1jXFyry(J5wbDV91yX`31p?&bOXX9zl-DZS z{-D;%_bF=IP6sP2%WJ&y=;WtsKdm*^ep36V!Lb;p1yi5XcK_twi1f)2xlt^3OG;~G z^6?8e?zQ`-RDwA-Pxzu`1%}a8PACX0+hgH>aAaN{*Zq2DOJPb@W^@$4-)>&GVO>jp z(ug`Qe$}(@F=&CqaSffFxZ6;^HO!9RVW^0O*+=%QT9t6Av8rv?V-<$E3W@ zK4g2z2W8a_ESLoiS~buRoFwk5zsuGM$;Vz}f9;$8~i=99&xlPVuOLiK<@1^-jBH-d4zr})J|GA8e54_aBK z-3)6r{CZ`|0cV0DY7E9PL3)z3TaG8SvG~9izo_QW^1y*e{NdsJk-}YWV*qHvH_@pl zap3O#ez1EJA3v|)5}XhR7T~_`ImWa+#n6bnBU;<_#=Fn+DDwWl1m+Z(?BKZ zs5G;rI2&VTCi0jCDaM_giJOEtedyA5(ruzVSz8HQc@t;(al^X(Sm$6(nfkrP&eEA5gy7hsp_Jig|DSR$Q z%wP=NSA)d@+ASs9!0wjgN9BWLuk6Dre9UP`Bfmx4sEIZl!=I5R+b`m`P^G*!W%wb8 zkw)U|v^>f5P7DX4&)cvPW|xgTsn@Z?W>t7&RD z?J!16v@X2ic0RgrZ7-lTy0wx+BuzOr^ukLY=fmw6I%hh6gyK54T84KC=}^YKoIFs& zL78Al!is)2!DH`Xz$`z+BG|C>WsY;%B zU`KMCk7p*{u;4V*2qrwN$CHiZQOt1JBblf+()-?`(0WSxZetIZSYAI^DzN$f z7Ur-GAo`d05FHer*OuNr^E7$t;-b zDLn(fF&TSpDHLDA9fmSE2NiO!5`s@L^Pd`1jjVasnBGAAJ`WVh-L??EL5G85tcu0C zm%)Lt$zgDMS5|$wEQS;5yl^#1*c0#V-#Vx@9XLwb#kl>7zavx_tV_&zitYnDo;9^xLl7|3E`fbLiqjkKpRGheP!1&Hfc zAUT3r{kX-8Q>R_~1Mek7ea^)HQ<*1U8TOECY6Zv1f#WUOFoyMvDeHzYI9npK&xi8( zMRF<6QCso1zYWFsUAe>$|77{7R~{C!QTo$}cV%C1Rz{dqBtM=EaL2I9X^F>)65S3bl`*b-Q$oR(wtK$~20%D=vFe1^2<_pV;SDh(g zeJwIP6hygkaX?K`g@ggkRTUEh6Q)| z{LS75id2YI4o$9(O7h&@^Aq8YOCUFNMO5?Yiym?fSIeR68eh>anN5Pd`NtN}kJ}3j zruW*KxCO@4T^YBA(ULV=(3)zJDpDCQGW0;few~D1qj;wu_!9XZR3Hdtm5ES&a z2=vv1GVj%^K3_Y*?}(@nKjxKq@v6_)j@H25U$@m5m##?ju?SIwW(aq6<+X_ygYh+9 zN-F&hfiMK+wSUCV?8APN{5Aj1!KNe50lruJQB5z_a!HlvYcIIE2X$n|KWA-AjVs^h z)qCSl)T$2oEBD!v_(V>~SQpIYhrNt{{<<~Km_#(&8>XQ!EcTp>W>Yi{Y|j0sF9)6E z8Ow^PmrLjqf0ZL{yO^+TiVJVFm-^EuF z!1(;)9%U!nm+5v2i`y`)g~{e5X|NCbpP+Ab5Epc#181j6_`a`Img$xNeJ{4WCurW5iwURUB= zKFM>)GXH?(q+k^$hRe8){Mu|@c|a9`TCg2CDjPMNJfg7+G^%15*5!0?F zgP4Tm?|P;iAi)&(sY}@u3+nm_u#I|kQdNbGk==<@l zwf|JF*6ymKu)B9xB1$1Yo}$K}HGfjP27udL+DH(KLj2b4LWe3Mm0Jhijk+^pSJV39 z0bMU_AJGCg(PaVuMji(t8%&RTpqah=9kjcM(}duo#Tz)K0hbm)?)NH+I=U)G-i2xq ztF-Q!EaMb>R?6+Hx-LK*96#P$a*vW=^T!;n&-upO_Rx_NI3R(dYrCy49(=y$O@E|3vZ@_1GcF@`tS^oMB%98-Jj)&{}-@2F*~B@fU3S%8SW`sn<^h z6SGG;I*N`dKlN*yLY`^r;l{ZX5?QJKG2p;as={Tiqe&R8N)r$B@S z2&I)~KDr^C;^H?`WZd5&*WROp_d$VlnvG*b9p7f30rhfR#T>DuKStEu$@e@$uEu@| z6{aT0LVVB`Z7KZBc!DdfZtTu1DcRup^TP8;fDP)nsvQ(Co*i*qjj~7mj2=_a4jtmt zxpj=if!LVSv0#E}df=IaJvkSisD*`d6dCwQ3a!Wvs+i6m*K4o9(c)pHf;#QwKP!(8 zSyorF|ME1*%GISYyg4#lL1#H3R_}Q}0mPY4npRkF)Per$y&v*6s9%pryFO?PFm=}g zPw`#HJYDClhpe92p83s0%e=`$re?y~*%8G9dLsXf$yd?y2S%**vzos;*k>V&F8v|A zErvCGV3`U}ol|x<*8s+BpzZ3(CEas>x8T!OvDfNd0CnvL&xHqp!gTDOh3>5ddRLf&r`^rQ1Ho5jM@=U!jmK*n z!#{4z-CWV!IO)>bg@zr=c~7IxrfB%tGE6FRr$UC*UqmdPV=@|*2Yx;hYEt9ci`NuZ z7kEiKE!>S{8vco_9%L}Gd50Z6{$&M%$#Ev$J(JRwCk*U%kfd~ndlxwEP4}Z27-d+8 z64hF;UwS-@dyL%!OHu)Vg=_}446F1fzp`!Dal7oO!8Qtq3RPq)_^CVN%+J#i7U3Nl zQDXdi?0%n=)d%MZ{aYe0ZN4mfEKpymlWHs|>dX61=_)11cECkK;hR^XT&J}fJ~MN3 z0e7ETJ`T(G=4h!6$EpFy+Qh|XsL?SRn=CX4EPS|oQ2rFxY#1Amj2b@bfaajsoRhGA zAkeBpK{DtyA7#Das`Lz$19ABXgaQ)$(K@YN{TAQ#@Zh-^WO<%qif-E42I{Vy6AVJ5 zbsIA>eqRU*Y#uF$#Ny{W|IXp!Wc>TN*aVQI{T`kPix0^_$52k-qk$f?Iw2#6Ke^Zy zxL=_V`n23!_p)5`+m6oi;-;Pd;nmaQVP_6!T zcgLE=OKM38@7f9kpg5ZAl#!j5@$f-s6Q&W(Tz@oWK}be>q-WW}(K}|^Js0N`zp2**P_15T~5x6cvkiQKDKyJtqP% z`2>qEFK~4!*^pO^@!!HWc+b2BjXn&2Ww5v5wBd#TJK?Rv&+<2fJ}Cdgzg^=fa9t>L zv(1z~iikPmgGegqxyUzVl}AsLSZ*f^|9h=i*R`BKLzX`WGQ?+{l}Ek57)TG!=K){m zYf_j)$sKr^7N)tj>3)Hgj6ty_P4ma3!HX)DSW{EaXTYGBUQ_|oX?czXf67bGh94~W z$T(f5cK#xry@&zM;O-;#2XhmI%WQc;Qv21GWbgQri{ z#{lxyQ4aI&xJK~sQW*E4_t(m9q$IR@NPT(`y;W9N$2lfj;o4!KVGBizb=iPZ+oyWg zjLXw#d#YWKUC~)A9ggwdha?k?VOSC%A*&f-Hozd>bA*nyWsx}2E+K!G$yZ<9{7tvl z71=Uh^k?;n_y{FLcdYefbbBp$D1uE`=Sp%P= zDUzUW3=kj(s%Q?^4I8TMFr!w{LJV}tliUizVASghi*erQd<>M-$o$UPc<6!M!$!xJ zIly9(&rSX|-P|*`b*=4D6Z#}m`cKAA)N_iJleMIVrU}WFgL-)HuZ+`|SIIc~628bj zzZtR@B67wfAu^@vG!UYy=@Uo3tk>2u#i-U1k_2uFaV!j^zH%-bCnLOD6F4zy7;jzP zePdUo^=54aq_>Dt5*6yNIiP`(FiCNNkdAG=s}c=8XnrIq1QreScLS9TN$JL{eURPA zbb8evmS$C!qKuC_7-KP>gftP6oa?PGRo$l130aAKa7dA7Pjw%+P|&*?_+o4EH#d8g zs|O5|#@2u+`7AKX1pV3ZLv<$mWc6i)gke;U=vcR7^R>0G7)tKs*+?heSqH5NEd8YkfR#A02D3249IzmJiBXzKB1b65GQjjf!sK#$$?g^pkGZunZw*4DC$&)xP__58bL?WT&>=F_*C zivy)z^z*<2o%w3-WdwlUgC;!xg)VwJp*(>Bn8Qt-y&ZQ9mDoPewx8_f8%JSl6X)La zpfqlZy+YY3V208jIOwHq+^MgH<6UQ14!59NT*u_*%4oRqIZyv(ot||TM&V94x$|>} zkmCr=`_)LtbV8VRcyCBFLFhA2oO*>eFG?@Sz3G~QZDAXxQkZYr@ah48Ouq9fTae)0 z!>9w+<#qZGdvvtoY2w0RtJo2yyDi$TXEPSpl%Ez;4tpRx7(-#IdOSw*a`1=4>_)OG zOz7F}Nu!-N{xq#ozg>ciUkK$&NISJCV@UtqELJNbHm+6|iTef;CDshN_4=;B_F#0c z@dl%O^N!-6cwpkyUBy`H{*9vRLh!Ek=Q$_$(wt+4iy?cQWmIT1(F-kxp3?R@Lf=!% z(f+mCFjxES=VDWNoQZp ztgW)%P*a*}VQ?!5NzwGE^FjMDpgDN@?$v>Nm_|>^WIy+7gqscmqh?jx@vQNt*ViAADgO^>Q`_+l)JMw3E zZ|Rd{`XZti3RecKpXoZUi@K2bw!m+Xh9;Vo5A(GJ?H1lOM{l}V>NZOR_9>Z=UL|@v zM+B^VA4BSkQ=!={<*MO zJ>hb?B97x6?b)De&vc;h@=ucB)yKsG^lDXWgkG}XIX$!deO8o{4J^ybvm4@P|Bz`( z)eU=TUyL-`X=`3@NcR!onzN?1stzw$5^ACkeCU61AoG7%9_OiPre~Q9_8iERM;G$w z&rPl~m!EOKt5pR^Q#d-TChsgF8m`sE8~Gld|2vqX)63TjPdSdQvuKT#Fs$kduckO3~k{BC53{GURY? zKf-A$DeQz%3#l_yih-(DGD9Ap!422tx$O1nedwJF^{h0l{EFZxB4(op(Sfk!QuVqf z5i~e?;Jl0mxQQp*sWV?sB+9Tb7$kIo7$K-C#}K|khNJx`p0u|F=ziaKMrv~>9(%T@ ztfF0=$*UL3h?OTHht@PcOCRGXpBziguSMqO!l5^>&Ny7~PmKdTG{<$=eNDlXYHy<> z1~m4ii)f6Hn$1-jbHLYN`7H>&##2rGFSfD$;V?IY9~c?hLQgDe0iwH>SFQuEtY{iO z)k)pOXW%t&Zsdc37Lp8)P+2MZPBgPFVO8)`{Ng7-X`$o%HlLK9l#79>I^`v_&BWBq zjpVDPPAR!|#bI< zgE6|)zifk&dwyr>5UeF~(uvyK363Raf--S41~sQEaP_^1&c&PeCS@*?%+@PoB9P5+l~P4`SLd?Rya0W&1`#u&3JjY$!6| zhElp<_2Y4EZNqlANM@~_kKB55N;<$O*r+`-h^yP|i+Bx)2z}E(JQ8q7P>lElaV69+BSd}fra{cF>a^cZzLr#O|oV;XLs@iTiCQ4QSFYTGslAD3SmI3D`u1~`~>YR6F zL-Tc68h)zU*6et#;NaWU;XBRiRoa^N3QIG&Q%;QzU!}RxBB#sEx>Ox?Hw9`Nvg=pm zojg$o8nz*P(AOgcEhVr=k}Zz{dc9AbDU?@2;dF=BSXE3~<=9@>)>1w>qo>gM@VvGX3DkXZlXm}UKWP@BeEvL92Wb16lHHs_qoQraL zOn}IgBR@MXylx{hQQ5CW0zZP%M9i7DiAC59RoSq$U^69y;8s!J$E&rSZ)1#_>w z(N8XXzF6#ng^(j;>OSUsbgvD*j3=%_JcXVsaQ;<0ofQDRW|ERv>n@y2o_YQ$`{zq! zkRJ=}u;Iik#*#0`J3UkQ_rs-*#$Aq8bdZr*f86>)s5GPzx>l+K&4iTg6c*2)v!%vr z?8=YGw{az6ht8*9rY*&F?~F4jTc*2LBd32JT>0vddhvSK_N=O^))R)b1dTK)kSD!k#kpeUhFKY>i4ePA(gJXpDclV7!Lr}9J~_*v_d&I z9QNC8Kqe#V1sOo+l?U^<6nAbP$o??}^N>0-i&#W^yKKi_uHQ}1?DJKrSedyX8a8W3f##B*zwAo`o zG^5K{B`ihusw+Oa`_8c`zQe&r=Ag&^o&3BJef|=s*cH3A-?VVRM&6Hh&O={p(M!mm z54AMC%vh@euDkA;yFIn~Pd*N~huIAkv*EJgb9(l@Zd5$)Ku8km8*TN|&_KyZ8h`a( zdA$+zn(2t_;w>LyW6E0j)WtnQ1;LWgvEynohwa*iX>yT%LK?_<9PNQfEwb8?moMS; zQFJ5@26W|Ek@+cC}he>cIkl^>ezEbRf)D_{uOAqMeq|7N@FCeUoIG zoBlch_{9Yc>ZoZQgB9O$sKmW}>clZee1BzBobovld*H}hJlx9|uCkHURC`}3h(E&n zt@p-iU96o)@0Ax_xiJ8BtU(K{Ft} zu>xw&Gm`4u(HCKMhmX_zyQ4xD8+?~K%s*!LoG?#RWW3g6mP;p`cvXrg*1L2?q8s1a z7i_Ct2^!$-^hYE)m|1xSG(47N(XUJkWt_M#1C>LeGM495Gh(@xUh{7`B)i3gw#W!c zY)s;lDRFf{4HKWHIIqh(3;ysntEg~$93OMKyXeDcQ~dN zO{{Q;_~xNy{s2b+nm@I`Tx8TqPgA182dZaeX zz)azDX!L64{cBDPG>;N2*e{r=MFAS}_Bsz4Vvx{J5|2hEPcqfpK$tm60BA`O$v?x~ z>`}nBk0z?Q-PKE59m^EYZ8#or#jP=p$P!NuoT5!c|9s`tuvHH#wPo6$KqnE(jM{)i zhMpA8gw-!V-8zp@GbP%d$57Cyz)0BnZnx)nksNd)%MbSCvfU)FDj3K3HJB%el9dOK zH8xo(MOPVFuxypm__A&L7WQUO ztQ}FSNPm|c7cC{(mGSXC!UJnorcuD!3MRBLjOg6ml_kQ`V{?_RR}&ivq60jvQVKRa zos2&tv!?yRWtLB^?1rUte1B!Eq5VfHYA^d zap7>6AaZvD+BV8-{8YVYv)(ZMbeBQkvChF`TS~y;iGgQd;Q!3^F9k-Be(L1vn|IvrCSaUNGV;@4jo`pI5j{GdxP4nK4G)M#% zTxJLY)jN1*8W}Z8!pZ@gb`a+-mrp`n4zZ9V8!4dS(h0@qh&dq1HH2Q0UvXOOU1V&5 zNuF&|C)Xaq517IbeopWd%1#iWN}x_07N{5dJ%=4oU{Y`Lfm6332%?>{w)gM?+N;2U zvhb&wd*{RlFmlXHOc8>*U~pDY-|Cg8Zm1rE(Ve&*o0~|f389p>H&mSrFb|8bT$(fes*mmQetc zWdMuRN5v5e*+!`g!XcEu?g7OIfg%jRM3Eo_h2dnN$PGFLBMSSY$ukZWmn(qUOn`Xg zX17fk2Za2y(2xq5sv+YAGK3kH4F|9T0J-{%+-CtR9gLd}`aEJrrDUob7L!A0r5F|t zkMNo|qsT>~6-84Dm<)J(5J8eeoB4wzjdMd17Zy@M9;`eoK^`bmH%u0)ZJ0bqj|N3> zTdpfaX_BZUNUEZ&RFE(FyTo7Yjz6@4Yr`JObrLKgR9Pt9 zU{M#os|cm0A?+Vk4Wlf0wiUw+T$dH298d(`!-pN7oy6G8G62+_^amoht{fuIZ7BKY zEzK;{hx`rMs~%>Bgdu>)96+c+lCdAh6r(oRMDDMi}I zGAl){?eW7nQSujZ-7rb)+l4{(Ik z7EC#~ceLSMfOrpIoV(h`__*&UMk)!NV`2&U&us})el(It2M+1JsM;Y9bNsfa`jzOj(KzD5M*oQ&w_9Na;yDQ z*h(I1O(qfXD-P9OPZNn$Ly>huA0cQ5$F}s=2bFgLtzm;+>MGQlK&DC$zvN{RL>=4p z2>;WLCyRb*?IWJY5Gg%ft6?!Dxl+@X*jfhL+NiPCm7{0Mw`s#{59A1wKrKtlHlNWT zuN6H5)yDJJ0=ZZU6gsFYrhZ43c0@vX@~Xk{8}{62^4W@xbRJO@Tu^tl?4iJJR#nDZ zmnna!16CF@-O@gMc1L4Rzn?^5?Yme1B*?J(bmT8zqFqqa*Ct~&23SyOeCod zS3p_6GlUX0UB66VW)O{Ca#F=b4N^IDmWf4!)4eSqpI9J#2UA&9F?fESH8ovxwc-Pe zVlD7t1)_O1fG}#3a=^t|HuL)00@(au4q|b#8Z_S#64=E}xj7dvRhQ7)?xPO^2|^T( z5FVQ`g6Y>f*eX_-bA*B-G$XURv0yU6i!}W%tt5w)d$hcI6Nn6Gzf~G+BDhba8L*&q zZZCnDEmN{+rG8~Z_#O#K5rO3_lbZ(T8QAaV2r~bqL=~ySqsGVB#2Ch8OA;cQWxMS@ zPyr}Dkf1OmVnHlC2ZYux3tUg|pTD1w2@EfV9ZJ?lxky{4{;_^fk)}6|117(t5SYa?5`vM(=wv1#Rs) z)0tWgC(}jZacJHUa6cFkim$iA;wV@kBKuLpNSMHZ%2>DpM+_ZXc)A2AP^1f)T7}Af zS~hTX_L?zi0SO>sf&}*>OQ2x|4(vdSpri>E&HRu-&*(q60T+r_CrTRmM=D9PVBrK_ zEMdj4aRpayl8&2a8XM6NtK^Qust*e?kRJ9Dk8K`hx+SQECb*gBlJVUxPC%hq$bp++qA|FD%3L%n#<1(+PXbd^@Y@7dv|)O50icZgTrQvO%wHTlXl}}W z$Y}l0fcziHd*F(Ie^ln+=jw2m?gAMi5?IC}>&i2l&i-1;2l$>f5`4#ETRI5hRJ3GH6&Kqzqv|i5iA0lc`atSVXIquw%;pf(3#C z5zb}c00|c|`d(yz2_mKMmHq$ae+656|H#U~!oBE_eXA5dhG%Rz(A57@;MvmJ~9Na$SaoGexZ-Ip75C*{bxK-5_qD_6?9a?W9=X}p;iwxP(0%#mH(DnExJ7Ir^lan6*}vT zF*(kaD#dG!$o28o#C3@36`wcmgZ~1Xnt;37ZnM8FA_tIGYHmYGT*4HzugKD0T;j>n%I3vu`JH;VjAf7-!L6Z*S$PZVr<2=) zzup86A!km*Q`nH;Ek(M4Gvjyn(t3{vv-v+?BLcb`3(msz|d8-ftb(`EI!w5=arEm}%vV6jAAn3MF@IELaoYZanB- zmAOMRUBu9~$^bZOL&vKO;hQCOJciyUe`%Ei^jTbpo0B)v_u6o%$$@np9@rr@;ej?Z zDjTXmkayD}fZ%94R{pZF`A9PgODnP`49ojkk}1y8@>GF5{G^tB*iALI|8!8 zj?L$K(Y=xKrpAKBo&7n|e9ke%GE};f8l8Kn@5vy;xr3~(1dP$h9WTCjyG$Zg?EteP zqyxwK$YK|kqM9&J-8_fy=3U2;<>R)#Uvn5rvGhJLHKXV%JG_pQnI}8Hu7loW7}|(f z>JOo7on{brptQ2{O^UJD#7;>05kvp1RfNYX@3?1>TCSyu$}8#g*2QT>byn=a@p@)U z7zjHt*Axi_VfrHj!8VY(}=6A4CC0C1sN?w)gjbiaJdi z9)zV|wP-{^Xj!^RFX)usMo$(+wW&LR4_ZNN3*z?hVs-?=48L=fa>VTj zr0xiO$7T^b0_x(tEZ^%*l%%zvrtPlpuC~cjy=|A&0-BS5E34l-dxj`A`u?*Og2!xB ziE@&9bFm_znFneH?j+#Gy{NeuPH43hDJmCJZvPmIUkNEPr4&}IxdPJU2S|Y%-q>v) z;JR!J_<76hkiJM;2OHT`kscVxUjW=* zqCo$rIvHlKLt>EQ8L-putxPZhs3wXC6ZtwUpr9J7@Y&f*fMz`7U7K7Qm{^4_P!T1# z0F;;ljpv+^MzV>gRuqbygEZT}h`PNU1p2ETNA{q^YHYKzq9T#arcvKiY6;Fx5G&N< ze`CO1bpYqO z1iVeGpOg+?TWkjBYBw?jPW_Gfo&Uo8zv?{(8SRJBJ^!u`cpo59F#HV8et<1oU7KWd zmZ~-+s-i>05yorh=H&=A{|4js@Db$j@GgMe6csa8T3cR7=jpLOB7D6Qc7;Hs4Vm{0 zOJ`X`qM7rd6CrKQ_j;E;Cy)IAH(zH-Y~TtsdX-+^M%Js>jVj{Cr7vGaVgHv@tATo_ zegJ6^Ld1$C=Kvyminr*py7J+X-5xs~aPSM2Iw^KQjQdepj__sI&&(+CS-n=M%P~Hb zG9XG43r3qIa z?$g=0c0_+#D9DT!{E)o=Hz$vXD3&j2fltu0Ibu2@nBXp1UGcEJlAS?FU zqrD074%WLHc~tOBk>G#bznjTExx?$y6=e`Pw<r2L|ec z7>!}lLn8-uaF<^30HAM){kPpBgF%RRs}i~(VbS)DtG~Vha5V&dblow2AFe!Y@AzJ=?>tuQmRU z%LLq+yU?w7-sV*)pEbS0uD7e4&)2oB52qgPA=D{IF4|4gqtLI9!7*JWkLs`wv(uCF zDnVc@a62eMY7s)&X@;t$+5iw!bxh&H-gyGQRZm%gP>6r!{@X>cY$VnMq7K}osf3&P zq!awyF9|(_*+^P^&)Or5gA0(z*a0&iX-pyFK}x=r`;!@`M1pV9NyF*QXV1+)9GL2Q|4HY$| zsKZ1iyMVub(P=(#kUrSJe-Ry;5PpBvtxx!nDAhM?djA9LDh!BR=sxJ!{O+vCMDBk2 z|BhdHzXKTSCGa4k+P|OK>WEdn|x&HG=_wVp#`y2ci$0=5=^gu=^Z(<#!9C2gYK ze`Z_JyJEJaXl+ffGdC9!^=o+ATbZ>sPCv%^HE}m#8| zPSV5-x5;R}>tIk)3!`#V@hf9p`3ShD^At0Jshd(YdOrFrM_r`vGAxd&U-YFlJmCml zFQW&`$O(v|gA$Oy>S=hi5!rTJXc(195;7A5yh-#Xz;==$)nx@hWZWmbXv5@`-OaPX zc{2)LW7k~+`W2a_*Rw}K*!$AB#TL(A%i0?<(9%!Qb!7cQRL5@%w|t{v+P-cx1uZk@p-9bsNL;(y1ht;F0D><+SR3~ zlEN-J%R4FhzTykq(F)x=4^FMt&D=V&q!yjJoP}N>pO4ZREuhlXv_YlaUUQQa1MJ1j z`l6jivc5U#q;1y-+2f8QzJUG7%3J!F|2nk$eQ)dQ+4<8{obT(kearXhrJH8bb)a&+ zjYG6I{ZNi_!}cP2WyGLsRmC)!{MW8f)XIQ{w2_aX$79MBUdz3uP^_*JokxNaoBc)D zF1_neVd;W!Q%GR2X6CZKegSo?U^_=uSadq9D7cnpY5)5A zTqSod{V#+So?oRCo_x!arM$EaOqo+pXVIFcazwQ}E4=C{GN zY7ZQM0*KGR{e~6&pTY{dsQ-mc-#3Ob^I1FT2cbjYYfOcCIa-*{ph>`j5V2Ynd^&dC3c z{d7Ks1weRxTs4TO#1}M*h{|(_(L{~LIHN`c#Tbnm z(_nn&Aac<*XQ%?s7e7w z|5tD1-#Y(;SI-=D!D(L%E-iEZfPfB6-^9(H5yl$Sa? zfABv1z#p&p-ER->_~VZ6Ip2K}-}k-x#$WupbpD6uv2F8< zU)_H7v+l4Q@-Rq)9ijlit^XuQ<_RRbN zdmtanY0m%E4Oa}S`_0)ucF~v-obJe954-Kg-Oi3yx#(|i5dPrnhyD7hgTCr>I`Tr| z^wfxjHQ;F_s|WNv~Etm)6uq_ zf99aAg>O0_bTXlKv?_elc$Ok}pgYp}Gy0u#zH3wX#>H{r zEdIKyZn_>_V>mmiE&Hup2e%i;^dO8CwSybC|4wR~{J#z@k#pe`XTzp&c#hjt(GdtDL_$i#L@hqHa=ZCWwKAh`=;L}i4_!J+$>vJ*Z=gdVP z>|!=oX&*Zmp_QG#SJ*bj;Ys3Ah>69e`0$-@-F(_yZJ(XjW81dFi*_%*xDd;yi=Hn0 zuBA>xV_FpLZYfnf+%!c`7gA@x*2LSsZGVoXRfiMXTwSz#N%yuBJ4UVdE84x|#NvxP zzS8mS&cEC9yyA=Z>SbxR_j!B&eBbl-9m&-YgCFcuJiPIG_aA-WNe69ieOlM8+Kd|_rs@p-q`cm!!9cN;IOraPd}pH5$6>( z6yJ8_UiMo@-9>CFif=on;n-kIAwx5bBB9yi9sa=8)8lHCKlKF1$?e81z* zJO1a#UvvE9$4@%`gX6zAe)I9)p3vcheNH(1g!4|gntSLH*UlZ_y2r1(!Evp-Bwp>$ zjC20?@p?ZZUgZDcI{ESOXMVQp?3c%LeLnu&H^d90f$@FORq<8P)$s$-FXOADYvYyC z1M%i)YCJW1EB-wCFn&3j9)FhleY`dGFl>!KO??yBrMAVTsc++zsfKuti=us8J3^-I zUg!U5alQNBaV_WCL=7;SE4ee?;_r#`{x9(cKO1>@yoT^=Qg_6gQs2c}-EQveIL9?_ z;JkUxyNUDW-E7xsd(L%+gP=z|*Y%56x&HA+cNPqQbKrdVIb6suUmS06L*i<8DU2Ze z127Us!GrJ+OynGYgBRf?m;^7wWX|y_Oo7+nb$A!vgZE(?d;ovvH$H+HFcW6+TOY$5 z&OMj&e8Toqwx6+`$96u)ltLLSf+esNmca^G39F$J*1>wn#2bAl=nQ+p-f$FYcMSXp zj)#APe}~?2weQFG{n;Nt&Ym5w@>j9F9)1J2!GnDN2flxV?W2T$2A*SoER2H*eD@Me zV*h2fA92ho&cpTiEYw0B$82W19pZRn6hU!Z9d(K4MqSzO#{Qx3L-vn=V}N{#E`m$Y z-%YsT@v7(^w)e6ffqo=#ZPAnP6g&;j6Lu_&2l62zAEGyaw2x+S>}-ym&-M$prEC|l zEn~Zo?IN~|*)C!GCEKsqma|>T_G`Aw*e++gf^7xcm28P;w3_W2wv}wxvaRB`(ohW> zfHa75kO$Hr`W71Cdmueh4oHtwE7%>{KoJx}2k1!2-UGV8Ua$}B2m8Z;adqloI0U*w z@9nwNsc<@+0e8eRT^sJ(J^fm@C--U<_v(7?)hh1Mb=;$Cxs$4BukWDTbm1PF#XUcl zd;M*{I$p|sK8^dlCMt>Fj1G$zM@PkxPP%r~2<3I0w^kmHVhpF4IbckFxI?SpCUM{i&1 zALFQIvRj}VEk5eej#7(imr+8B7dKy{`?hrlqTJ-BcC28pQc3b z$9F~_x)Sp1PvqBT((`q4W*Rv&jhvZA&P+?y$J5E3I&!6s+STgd4wQ`3Tqk0_mJWJn zj(VG;mT}ZFj#|c1%L<`N2vtm|jfCnzsQHAdAyj5pdDw>(`jQmN`zPZ~J6e@Bq)diX zSx>6uD5-mpA~mGKQew4~lD34{loJ~(ahYhUYahMkiitsaAqL4`sG%R)j;pjQE{V&y zo;_$AHgHW})2?l>t0&)HBi~BNxAElLEb?t8SGCapk(%o&56j8J zYVz;{^00<0olhRlNce zRYe(UPv}jA-bm;yp|jkdc~XQni~Ox4Z?_QhI`V7_dA5a^*16XF`UZZvno^P@^hQE& zB2<=dv(BU0>IS&hj3J7lF~9bpt*fT3tER21rmd@{ovSXSz+|?s!W4K7UWfTm3T3be zmcUY21}k7CtcFTh2kRlj_3RD(V36xbJ5fy=QBAv0O}kJ{{a;PpZ}omP^?o(=el_*J z)$!HT@zvDv)ztCT)bZ8S=hf8b)zs(J)a6!pS5tRaQ+HQWcUM!VR#T@|Q>Ru_r&d#^ zR#T@|M|t4<)SK1Ro7L2t)zq2QsgqsDR4?cQr$Apg6Z(@rZFZ#Q2GVTqyOw zr1{oDil*Gzu7ujC6aAu2r0dy~hsWZr{(0AqvarFAcg5tyXWWZ*&KLe4PZ=9dPLFXn zY_D_oY_F#tn@st-l=5{pxqlPKFQIIeP^O9~Q~$wvELX3gOqGzc*HStMPgF z^^CW;BjE%%5gvx8;4knrJOj_d^YA%*0SjOutbw&q1!?+j9bpgX0(-$vU?5xzx4>QS z7gCrK?>UbzqtthRgP{j-Ez#k?^+ZR*1#lre0e=RrDVhe`;5+yS{1amCKo2R{4O&B6 zXb0`#P_C~xF-;TGG%-yR(=;(n6Vo&?O%u~JF-;TGG%-yR(=;(n6Vo&?O%u~JF-;TG zG%-yR(=;(n6Vo&?O%u~JF-;TGG%-yR(==saHnHtUY}3RxO>EP|Hcf2P#5PTA)5JDS zY}3RxO>EP|Hcf2P#5PTA)5JDSY}3RxO>EP|Hcf2P#5PTA)5JDSY}3RxO>EP|Hcf2P z?%!Px+Ranq#k8AC+z9q*#p&Z#(Z{W#k6T3_w~F?33H{M3`l40zL#uo*N^Tz*z&^rCebtS6G_r9rsI}3a7&vT$3l~JGhAZeiQe6*1bU; zT|pgPK^E8IJT zdzbLT1AkMdn(tDE*u zprRM4hWkaFu7Z>*%&TtJQaB{k*>#vUsfdz3TwSm`S{ z2iNS=Y%@>|8(<@33A2f94r&Qg$8T(ATaWw=Y=Z{)9=4;8<9b9fpI0{jY`HFm5etk z-S1rMc)2Tv{*1ZLf&p+2{2VT(|1*Trb16(leif#`Yw$WSW}t-DQbKDfp|zCI3QA}N zB{WY7%~L}2l+ZjSG*1c5Q$q8U&^#qHPYKOaLi3c+JS8+w3C&Xq^OV9`N?|Rfu$EF- zODU|S6xLD-D=39|N@1-ZME~tU_W!{CBWxe#yC)er{DuDbGweT48$TBPI2eySfpFGK zeTnVMz;9B5@|2(oN>HBClBcxfDJgkMM+GILf|5}|$;eYO@|27`B_U5q$Wsz3$o)LI zpC|Y8BUXoF{klbWxtk{k^WN`>xgL`F|8w}b;PuenAQ=~xx{oXF`Y|H=MvNL#B@9{9ZyWh6Vvg; zbUZN~?|wobub7cRF=NYO%5jEroS__ND90JfafY&+q3mWTyBW%EhO(QXjAkgK8Omse zGMb@`W+%4mi%nxTwlD5Dw5XofPHp^RoIqZ!I*hH{vp{ADP6nL?Qx%XS_P=+#;p$ugxHyO%JhH{gk++-*>8OlwD za+9IlWGFWo%1wrHlcC&XC^s3(O@?xlq1Q6oy^d6hc{16RF+w-CheAsu z7oMDw7fqv=CkbyOn5WtDo6%SxCI4?nG}PJ~sI@mxYj23Q^Q6Z?1g#((?Gz*1i044p zE_E;*0*rzg0TnX>DrN*!%m}EM5l}HBpkhWq#f({JFbd73e$NQ>VMe2jLK*k-e3o(h zHb$rou05ZjjQ%ep1^dE};WYRwZDtkQEsQ_UfXm?q7!9uw{z}RVFH)dC&jEHmX+0bH z9OUzt9o7s)4=U3n(f(v!;MQ^^|2fjyP1 zA@7qkIw=A&dxy(&}Ey*82Rj*nZ52qz8TXo?!j{-pJPX zAH)-X>-RVI_3I0L{YUwZ(Gkzq7W-*1opLcJuJ;SsU&Q_r_P?UMET^AVMXKiGdDQ7? z%1$l)tVPuAX-2N=qeJ2^spHc;llzi-KFuh09b<-i%2zGV=oT}Iox^jw#xcYteBU^Z zsHg1J^2}~=bOn8+tKfQ$xdGj6>_5c*X!f6@TrzTt#;_gBb{yOBY$p)rWx~8dn5q1( zjr`xDX8bU|l2P!y!r0==^r{z= z`eR7_F{J)vQhqWiKa-T7Ov+DYl$9stC)0yoOmBHHDL=-)$8(8kY^PI?&Eflb$P1Ad zA=7Un2iB7VvwS7t(~yB`*Z>=06XYPzxTl`&H?R#F;CoWn1J_9JcQL)+#pKqf;#Q7i=TOJh`@j9NQ4R!+Ac8$C7Ic zq8aQn@+9{rlXH{FwaMhzWO8dJxiypAnn`ZWB)4XgTQkY6nM@^U9Zw~0=jqNGIFep94jNo%E+-Ya%?O)HkKTlM2<}&$EK2FlgP12 zQByw&NIX9J@n@Y}2CFiD+b5qH= zspQ;LcMduB5xG=JE>)6CmGn@pHmfC2l3b`H7b?kxN^+r+T&N@$D#?Y_)M%Cq zmE=Mtxll^}THfByj$h;H;vPI%T*DL0DLh#$=c(dq|4;6!_Pkd;jJt?;CsAMC z3=Kd&AFk#KuHn7bwY+th691j2g{yg5*vVZ%`lq>LGCS^=40%ybUf7e1a_*Qq>bMMf zQBEF|lLzJGK{!1?c~s8bQb#_OlTYR3Q#tumPCnUaznpw3C!ZE_x73kO<>XU2`BY9mm6K29 zY1g zjyt7}x-P?=vWYt-&7HE4ye;QW$#AD+xKlFRDH-=i=E!t(J?V`f2`9jbaB{qc99lzt zw%U#0`v+hojDiQ@A$XW@^jLY~SyyN*iPe7}A0$R-z&}yE5R+H0f$muoY^lEZ?wf_ma0X+R2$o49>*Rs71{q^ks z25v#VjqP1*??XQd-r)E*k>5i{RM00q&P4ILDuXG%eJBFYx_T&h-}e(L02hhW+MAwXWA89e&gaR!I&!a$+{=@Dd2%XGuH?B-tp}JVXXMF{A$&MN+?M~r2YhP-o5$GO(kuVA# zgoj`P-_2qB34BJczo|yD{%)EwT0;3OA;xLSW(j4pgmPIz?9={!*MZnuzc)>p?9f<4 zF}nDO?`?+69CY)5Hw1nW`X%f)_QKMB1u3$Y`nQI#jKnFU)zm~8%4rE@w1kwhesDTE z-F4Ve<79T!G}iA;N0*^*tYy|y9<8QXPkE%aL4On6%sH$#bvwGd*}n%KLjN2i&@nI$ ztT*)n-@lB0D(8F)-eJG7cF9m4J5U}=D32wS#}dk83FWbb@>oK7ETKG>P##Mtk0q4H z63Sx<<*|hFSVFE?pV|7$)>r0@3caft^sZ)*Gvg><^T?Gcr2Z6Ad>mzK9A#??DL#c> z(+pC33Mo8=)SW`=jw5Bq6?#ew*;+5@D^hfMJcpDkCDpznwdRpp^GK<2h5qMYwnKQ& zJrstqe+4nS3asaH8{1^BBu(rW5&JALpFq88y^kqe{S>Z#3Rgdc-p34jA2aBE%%Jx% zgWkssdLJ`V{fSQzSMo7eV*Rc!3oXM{(q3eYKwWuOt37wAyRAx7KrSt*2D2BQ0vUx7Pa_`oFE= zbaM1uMooiZ2yaJ*!e!`&Az#n-Cb*e!53yy;%e_^@y;Z}#wVr!wJ@K#No?0I08v&x2UCWVSPI5&(+c|sO8sl^bPX#4QlBd)Y3PorEgG6-=LPhK`ng)8*@eYc5J&XLMF;*cYibEI;PRL+sgIZ`=C>gGt< z9P!yi%H~Mf9Ch6$>bXs%Y>t%8QNL{>b#tU_j+D(&pKT&_bEIyL)Xfp^O{8p&cliA& zC*gaE#u$HapJVBOJz7-zAJdzwi0a0 zdYCQGvfMbH`nBh&Uwh_Q=1K7!DV}o!fSD6K`OEEiQk>iMqWM=BVqI?s%e{ z+wnv>=eMJeDU%VjW=>P{r^-2UH%sp3qNAAGbPU^{!$n|Emv82n;pFtaFaq63;F_Yw zC(XGQo;2rp6OfDEfHyh*ZTNuwnVe@f=lB8^z(QCIUqU&24a=bdh!b-f^U+$U;#ltO zs2aGhd6SUiO+t=02|3;*R)+MT~erhtjBNjsJ21_{F9Wl-v2;ia3x#~)?2@w?F%p+=yg*<`%?~f zmRBpQq?NZYxyj9f`8e>L1pnA_QgW#lQszJQKlXI{n`S8zs~ zk-CYa@*K69qdst5xz74RAK_BAv*2S|PR2J}YdzOWFPt{MigHrJIHeBR`T(>@+@V{z z?s~4do@=(J(Du&Oo;EkO?Kktiwdv2J8w=yX+VYvqC^|5%=UVHz)_ShB-tEa1)blI# zT=Q6dp`MhnCl51rUHcgvZP$M}+bbFITRd)H|919AvweZ>D{RBKwdZUfai%n9TDI#< zc9tvY z>iQz)Fm^(l=Uh3?RZ9zyXU5})JI?hUM}Nh+-gdijhAn(!vwUqXX%_7U&bXD9V;e1p z%`k1CS8STig)sasnw)F@Eqq+_n7;Wd)z(Yo^*e9Pr1Lir`C^^f_-{h$3`{4@Sp&pc{B z&X4ym_`mu|{x$!)f5T7pZ~J%ryZ$}@zMtkl@YDU@{YQR=pXq1$+5Tfc$Itbj_|N=2 z|GA&J)W}x<-dY-J5si!6D7g1@nAS#O%MvJ1w z(UR!P=&PtaS{i*FEsK^%E24^MWyH#aXiZcZt&P@2Rnht=9Wfgqs);s4tVxJAMY*Up z%13q4=4eZ_HQE+^8+{iwME{7skNz2LkK&X|`BaojrCOzmQzfZRsRL36rVdISoa&l7 zB-Jg|J#}d6sVqKXpgyp45G*k*QIshf`Il^{K6?Z&KS*-=@A}RoFjT zu^w{Yi*1D-bH(>}HD@i{-{aDKTJ6)Y?>^L&y_vJ!hi5o_S?@Q&?d4B$J$x^= zec(E{4@SAYqC;Gls5=Z{e<;j#J)%!xp6ii1!0nYf2)aTym{wQ=Wb1%JY)z12YlIYA zGo;uWBE{ZxEB5AFu{B4Ey%kq%greA6bA?%<%sNhTF*U4WYnqfx(J8j(NwGCh%1CsI zt&vh}&6Hwms1#dMrPvxP#nxOYwgyYFHCc+S(Nb&{g7PXlWePflH~NfElCai@@k$aK zQ7SgVRBXhl*qSlL){rT-rcALlW{RyjQ)~^IVr$ZrkI^Y}$V@ZvqF?obV?bz5L-W|*m^o;DLTd0+bOpGPO-Q8}&lkelKE|vG z3TyrBX+wyu{Zni$pt3hQ#nuWcwsuglwSz9A)N9kaaDNl#>gazJt3_68&o3VP5i;$H|_)W#uy(+^QB`dZrRjNuGNp zu{FSotqE3ajj&>Ch80^wtk{}j#nu=rw&qx|HOPvsNmgu)vSMqN6Vr%jhTcfYo zn*9)4zpvPnD}m=jwjy4!74nL$m{)8Cy}}AB-cu*w?eFSl*ou3_R^ThPB44o;`iiaC zSMEcn*ouC|R``cZLk?l(KX0aY!Q6qW1l^Gpvk;&RMyHqs0mUo|D8o2bF^dC=Ss+lb zNDv9Ut6$j+vsj>XMW>iW0|g5QJoQZA_N8Pkpd@Xglq{rFETj}HAlDa=qYKHwh2+>m za%dqrvXC5DK&mewr5BL8n@G`3q~HQlYyl~>kQ7-+3M}BN7jl&gxvGU+#X_F9@>aw3 z0_MUw-jF!nuDS8>E$js!D7K15c@>>v>-Uw{&?&E@Q|6;nO3^80=t9gkfMT`+l%?pD zW$2U@=oGUxpqT9er4pU84xO?dT?lpy7(*vu4BTkTAl&vtrbhoN1#)VL8nlD8OtOw`whwnbjnC{ zA*37Qj3iGXE0pKL>Zx%1Iy%K{MJQ%FLa9Qhq|qtW=#&lUlq@rF3K|4OwzOOKxY$-7LA8B?q(QR+ik!k{elCrB3k(*BK6q zN2Gegsc<@+fzH~#ENx$wwl7QDm!<8?()ML(`?9osS=zoVZC{qQFH75(rR~eo_GM}N zvb23zfZ?4=d)`5wh=qqA^M>&}R()OW{9D%--nabFUDWFHw&%6~W55x+b3 z{azRMzUZ{=ryqOzYXhGC+3<_UUw+&#?z-u;Te5fGao>Xv>^|zQQRNTM{NvC5RPp%k zPk%YF;l<*~Z@#ww8-IM`{Wk}^b%x*HnRO7wtc56MJw!2UB8piTQOw$iV%A3#vqqwr zbrQv_l_+MtL@{e73RX#&^`6A6orIX>6U8i{C}tT&F-s{SSWRIzeS(4&6|g-$UmEXqK1idkt<%xa5bR$LUb>Y|vHmk`pmVD)9^7V9rQfZ6+v)?mV|S%wKQ zD=~^$jZqFqryPk+IU1c}R%et8(J5w?M)@;3g>oDzX2nL?hEDkoonlsR6tjY(U==44 zSTWFODJR^T)f~mF=qP4YM=>iqido%J%nFZkC_2G+rM5{o0}DCSI7!Tkk78DR6tnW9 znAINzYdh39Nz5vc@(en~tOhBpMWx0`VpfHeFVHDwbtr`O1=Ki6%p#Fu7K#+JSQLWw zB5Irj1#3nfnPn7W){PXicBJfuPWcHsWgt4mtR*S8pi}NbrAyv@Td< z+PTFl6SdGTsD&D>G=*E%1yc((!5R{3p(JL_NjV&yawIzCXmrX2=oIDvPzxn7Yf;Ld z(J7Q|YM~_4kdidnl-%=(pL*02<_ zj-?!mPVgnn2B~U>S<_O?x|TA6V->T$rIs^Yi>{sRxPBCj=3f8}P zBcFh$K1-Tm76KHr7N(f>FvYA2C}v$uF>7NXW_e68>ja8fCR5B(nPQg96tiR&Vph#U zuyDpYoL%syv8own{Y)`yXo^`iP|RAIV%F1?yZK$^9(0OXTT{&Xnlg)H6|>H!n6);= zthXs<%}p`uZi-oZQ_T9CV%Ff473h?e=#mClUC}9KB|=~}rdg*` z%vzmd*6S3rW~Z2SJH@QsDQ5jnF>82=S;te%TApIo^OR4}DOlH|_DDdD&}eZl+?w@0 z#jNouW}Pp@EcGd7xlh58A9wLCxI-H)`-NMx@~4>9KgFy7DrOZ>F)M+JSq)UoilAav z1r@V0sF>A3#jFr2W|dGeD}{<#EmW{#$eodZ=NJ8&VO9po(Ug zMMT9cBr0YxQ85dOidj@t%)+8#78ez>z^Ir-M#U^NDrT`!F$<2$tLPN7@Ti!@M+Iwu zJTFUP79kb05UH5ONX0BjDrQkqF$zRsK(^Sm5refAM6|=snm^IE2EOYYQGl9oiWi!lj zr(%{o6|?NAn59p}EPpC{qEpN=sA85v6|)?wm?crgEQ=~;X;d-Gql#G~Rm?J}VwOr3 zEOqisImu|!N-@i($|D@7nB`N2)vR9m6QfYYETt;U&MH_>4Yy`VRWZw|%CoF}Qq1zI z@;nv`6zo>=j6I22YE{f~t1^MKQp~ceVwPSNv;3-4KXXVA+=mfh*_@dj`a6`6pekDd1z)J2}3CwbC2=!7FQiL30)^!!Lwi{xWcSE}IeTZ4)Rm?)Kas)c% z7<7tR^i}$!Q_SM8VitfEvk0u1gF^j{>NOU38Z@lwLV%CY3 z$I&Tfy;ymQb16>~PBCl8idjEa%o?&{){zynmaI%dr_h(;-CmN{krlJHteEv>#jG(a zW}R6{qf@HUDQ3-C$)Zzo=oGX5te7=uBF^*~(I|CLIaPG;Fjm9d6Cqv|`q$ zmEBphskA|-6roehdbQGlaEe*CR?OP9V%Dz}vxcphb!=rnbc$KeRt_xKXfr!)O_+6U z#jI^BSl?!*VS?y1?1(IHhFRxU%qoUrRx*?U=oGW=t(diM#jJlTW({1q6rD1e^C_>Q zQ_PyUg7phVNlCD%%_u2}Ssz!-8o6TD$rZC!u9)?5bjoUUidkM)uwue!C5c&P56K`4j1C$tw})G^;;xugcg3u{E61Z# z%nH0>R^gT2^k@`pnlM60g5@7Z2uaMUe27_lQOx4J@(AISN4XBgEYvGzv0gC?_R90D z=TXM;yUI9pidn!{%p$&G7V;Idn6H=xeZ?%`gw!I3n5F%Y&3qrS9a)Ld1<(_1w9vnE zTTE*h(hWJpEch!w2CC`lSwsYa)4K&NEUDLHfsmSX4~C80dgJ4!%r zq|w7dxNU<@DMF`oK&O~@2F1KJDCWIEF>elvd3R9uL#OPIPC1a?k#aCP#k@r*-O(xL zO+qp65{h}7P|W*;V%{he^G>1Qts*7(1L*~gZ-#lZP|Ul9V%{#4A*@bTE=8x9cMQe6 zWhmx7Losg}3ai!VRV2aN2EB>|w3cEEXsj+WKqmp zi(=kelg6a8M+Yjq@$Q;9mPED zDCT)bF;6^-dFD~fQ;%Yvdld8JqnKx(5WM^_#!0{!r_u9IxHT_8%7f^XN6;zS=Qr8B z2r1*xDO^8&?Ivp34>9jUA?ArliO~hnw{G-Qv~z17i z7eZRnCrn_ zZKDUMaN7o*QiM+FfKD;*QHpt!Qp~$l2%e_Q+f+z&O~JOB`JD=B^g@;V-=9@nimuKx zc|Z%84=d#y!YSutAxB{a6t!v+^MR$9Pb_6J$0@I(Q>LI(UPGs_3X0k{iCIil%m;azSzR8u8cHUS4Ns_e%loD z`?|u?p{0X_|aQ3mk(^p?;zjO`@wbO*RX|imu!= zd89zup=C|-Bym)pB8>7h;S|b4!Czju9g9veUwR64BCU6l*O3)n9cr?!4mDXls&#e7eO;D^!&V6C~)FJ-tjAC-#vtW?a0rGigO>@O$4cZ>PBRLtk4(jQBGidqFV zc|Z%8&rIbU!YSrcQ^DF8{nI3qk(F1`DO1oXuc1@0z(v0^$-7*OVm>_;^YN*e&rijC zfGYF(O{El_Qid)>EkBy9mLE-4%a10jzFq77k4|zpaY- zaaGK(t73j$mC%Br?Pm!SQj0Dmv{-2SSl((zV6l+CV$x!vSuQkxvLR||(Bvap;23lY z_dWf-Bo`qoBhV=$(S?x5^zo8B$+ap^5k@h;w+eL#{j?;nBP(jj&t$daXL3~wq|qtW z=oGc!W^%R#a_AJb;AXN~a5MQ^(m*l4zKZ$zRq*>uKP>_Mv_@aR;nw^DE9NIy*&VBE zN*i>FT5vPDnDZ$eTCn0~eux$GORV%kruh|RpytLMlqymxEz8_^fL1V4t;V5biW zJ6oggh|Rp?34KOv=G~3?jA;6Wq`!#Gy#Gk}itr!sw(|34nBQi_{5UJ-*I6-7eu}P2 zHF*f@z7_Ket(c!^WkL(9OJ@;I`52vm9WnEEoTMkR($b34-pq9pVAiu@en=JbpsAQY zbjAFYD&}=l!IK_!V-oYHt~^f~DCTcn8A~|D{IM(J38zfpnica5s=UJWD(2r^F@Nuh z`F~f;AH0Hpczg^cXtq+=Ru3PD4FN@05AXCZj~xl#em9{jicQ8hXftG$abeXl{zG{~ zp2YmsE9SpmF@N@o`L|ch-@S4sI;B54!GA|9H?tYV=#-P=F|>3^ddHvA(j_^CS*1$f zcrrE^lHi-3wV_D{AuAW4QzmdOj3RVOF*>C^I;BTEhE_63Ph_Q6JQ=$T zN%|lwgW{RAhD}^Y809{6%KglyR7Md_8BH9NC(tQx5QmWW@M;+{jqgLI^9(;^4%ZVh zkK;oYa(u`ljt^nhG%aQm=Ak!aIqRQ7Dv3i#8aX6`98!%OvH>|{BXY|hkTD5z`Cu)2`I-=ND*>KJ7ndM_)}W=Cc3k)oWya;>CC!R`V&q$ zHy%Ulon&DA1+90I^Eg)FzGp2~lEIuy84^#9l%eR9%eZD`80S;2peLl5*Ji~$2P@a} z8;beJR&F6)%B|=W^9-%rNjT*peph*naLVK86yEpILr5|PSs8~;G0)V>M1Dhg5uGv# zo$@mAP^MyuSb2+UQOwu4@?kud-awM+oKL|&x%nthfZZ6@h9#iaFu55Ap;Nk|Q@Wv3 zPR2U8(hHr^2c2>XI;Af<GW)z`QiqR?U(J4Lf8L9L{r}T;^(efwh zgRBgSr_%B_aUEfl`_L)(^OQpwML1r@TQNLZ%^yOlQ_^$Q*t@WFg^0%rkt* z62gas<6zrgj*YmGO0F>^92eVun(sq0$RX9pAsdiGHX?^?LJr9xhvef=Xz7~>$KAGH zPxz2;kVCd1hcqCEe2*MJt6!FYa!kwLL=pQT?T{5_>C*By!3KKxkYp&b!gEG?14(pjZ}KpHL(#Fl z$vU<-S$hX2U(atUI^H+=7UHVhicZnz0w&){IOQRJSJ7t$CO^ip%H!yi=dhftU=5jG zLlP__(`!hg&jn1L$ZsewqEjZJQ(h)+iat{?c`A01l((3%p?nyRqt}pRI{u55Ib4fC z?_g3h4nn7NMW=K_r<@#5rH7ED7qZd^opK5~r7t?=Oms?rbb`NCpx7!HNP^N^C^!K zPI-cG$}@yh-r#pbrXhzcL=IWbQ{#|IekUZ29Fjo}sYVXjfE=l2orKBvT_vf z8YUw2H zkrnJZQ%fhot~0fCl3uKfQTm`$u0yBXhfdLPm&v0Dr;O&Bl_$_CZ*aXK(~v`^GeajN z9Cz9NLc)hEB78_V?y~)_m?<5yoZ~|(xyFzxX7hxk`936r98!%OvH>|{BXY;6su^-Y7SviFFRw3Py zm6JG5(Q%i_XT){Q=+CjrxxAxO2J$3KIgeu%>H}JgB!fAhGK6?2L(wTZ?lSpu;-L)V zHC-EmdT^}UF9*3RUSvDJQwE}XC=Yo z8sn@acwb|jm1F|ftW4xLlo!z{lh7$T#xnU8;-*X`&y~06B`F`0zshv{%_(!Z7J)HV zrWpsJQ@Wy4x}g)IsjdfpeUzT82~v(kr<{OJIT4+5a=eDtI!SM2r7!*=74ti!Jb+Fa ziB1`XPI(ZW@(?=ZVd9~%J_OGjN&bSYJdI9y2A%ROIt35JPMJWuD08@Ga@bjkvBAq$a}HRzPJ=oHqbxDeK!gozexJvKKm~N4$pKP?Da=N-xG^ zN*{E}PxuXG05%QSiVUg&e{-DWp5H(t~3Z>flH@9G!9`I^}3|%DMcmaslC# z3(+ZqIaV3M*jpKjP8r6rN=r|ZuOyt((i7&Z38!4kxKp`_yismOr?m7m`F4Ioxtn8^ zd(bHl@N7VNf;3hBj835~i4=QMth~VWDN{*%= zOmxaDbjo~mN+~*}44twFow5X-@)bH|DLQ2tI%NeqWhFXgH9DmdowAK|R=z{0`~#ix zPjrf{=@n9*wTVg!ow6G`r8PRGEjpzgI;A~2<$!oKJ=P=#AuCYO+u-)+ zxsGx&&t;U}%r#eZ?zzc*nW?8tKqt_?n9^OoNtpy5l(r7 zYY7QwuG#)Hz7Ltss)3MjZny1+GuLc?A;*U-;`oqouD9(kCwu^{Vts<{$coOFHu+q} zU&>%~$`EGOC_~XHI_KHsVVqCVdCMm2EGLt7j%C&0G<9>;}*PlRoMI_p0}KH_>pX4C%{W0Y_!G+e2RImGn!G1PB}RqM_)Qg z?|2?9bdtXD6k6jX6OaX3wsFnqiB9PiPoZ^7(g#@?6whGJXcN~FM!652G76pY2GFSks}O4Ic?r5BE9WwAOVQN^CJ!c@ zG9;ct4V`2tvNDWgl`FWbm8;MxEzJqMjc|(2tutBY)|sqx>r9@&`IM>gB5JTCZxL4c zFrGkvILUP8xe45TQ<`xQI;AT*r5ifsWUT5az0fIr&?%>&Q~IJ)&P1p5M<=+|+~Mn* zaZ0?N+3ZRB;%ir#fKK2JU)PMD=#*aguT}b>Q?5g&+=ouNpT3uZUt;d`ByVsnA@6Zq z$TYqWnU0N(klFa+4VlC7A@h(!7IMCjMVv2W3E@L(SPK>qwPyWC$mz7@%DJpMRtBR} zhTuz98H!H1jNed(aX#gG!YMbQQ*I^>%0q-xu(QHwImsAgWgI%?WzMI(gHHL7_$o69 zr_AJ<1!{q+W*mf0>55M2hE8y{dUS0wPT{T+xTDrKqbEA$eoDLY2H`^9BTUFNz7GjY zyY0{B4NC~#xhe5Y%ws=fA?FJTOS|pkSvkR4hdkr-CHPC8!1H_sf)Kz_imxC-9p{Eg?e)frDh`~V4D{#=sw$jWGR z$`k06N^~J>nO_!yuMp;kHIXKKNCr8i8aZSGa>z#HkWI)TIpmN$*AudZYYC|*e8@M* zA={8c8jwT2M-GTQvrR+D7v_gGQN(^oJ7lGVXPOG$BA6|lbH9>Y&Tl9;pi^$)IOSG!%AM$x(VS0tjBv{1=#+`*lo!z{lh7%z@Vm-%!YOmm z32q`I$j!|tMyCvkx3cab$)(83EOg4p=mg)JHxSAoW^;x-N*LuCbV{CQb0Kwv32ET_ z0OrDPO;CcYbVC<%D6%pTopK2}<#}|iIroE8mBF!}lTE zkV6`fL%v52piRjoARlN~nkZsFq#d$y5;~9yxo$@$34_N zN`0`E`+qC<`&RDnt=!LBxqr9%w_Jbvd&*hplmY0JbI>X0)3a6ZYuC*G=VWxstLT&| z=#X5{t7*=JUHsDLSPLU5NVXG#QIC%}`&RCabSb zlhs$J$tzo6H9Dmdow5#{68h@2{Y-PPHfvUAlXON__C%+IK0bHu_oEN3Jcv$t1fB96 zzoCpJoH7obGKpgq(gWW(O<)le>#t4J@?A*igVOf5w?K?8Alm7Fa_6=yBfb#zFKO~& zgi($_uN;F;QJ<40tItW3N3_65bRpzPq&&&BDe805>0d0c(poh{#O}vyR`Avj=j%>e{ zupyzJBirB1_aWPnl^9(BJ(ygA*6~u_9yAg9J+l4K?~(0?evfQl{T`Y8Lw-X!j5o~6 z5rk8Ya>bEy4B-^&WNhUpxd>UggzHgmCcesWdNazs=#&xshB6Xe2xXL>Ruc8CWb#vl zQPj7R$HeJhzvUEYk>(J61BQ{LowYK`B^-X26`ld2jd{dcB54Sn$o62PMO=a@#_)=2Zpi_#_De9Zb zqQ0q2R^L=6t8XfkPsZPp(hHr^2c2>XI;Af<}0wV!RW_Onf1-2&RrHd*`G zCWrlO+n0W}$<6x8)_3mL0uQ279zmy!MW<-L)#Pw~z3qp6QroX#4u423x{y3`wnD-_ zsO@j%`;Z3YknMy~f$A3IPIQR&FHJt81&%?d3}i-&qJ2q|wJ&M%mCW-} zu12Ta%=Id_6Hd{-q{$-%^1fMrQu~c2zrgtw?#usi|4;jLCQs)#l$pd;(LRpJ=@zI) zr)VF?D-}B)Db3RYvC@nJGGGpMyUb3#b1@6BwoRr{3P876LKiBa#UQwT$LmP znNzG>!m-Mg-CCV_nW0>vG;$m-EKD zoHy3xys<9ljdeM1tjpb%%uqBxYzfHw`UH8bfQM}1`;e{tQb+@6Ha-7aLOx$Q{E)smA6@~tW1wTp!P}N z`jXNgCD_W^n~;Wh8L7LAW+`i_tto4=rlQGLvfe~#Db;Q#obm!XMPqHU#@b|wwaJB2 zyOdJ9lv2BtQoEE=yOdJ9lv2BtQoEE=yOdJ9)Oq(qf2Y64|K5-AkNZFSzxZeUc>jX` ztDorq=HKw|`S<-aKf}-VbNy2PwO`>Y{7S#tukmaBdSC7HzTR*1-}>*PC~6(GiH>nm z=Wkpq=USiF{#Wi`cYt%ecGCN;`0edHJz)JEfAPrp@whm?Ivy7Poi~#%zQF!7KZj%7ZgB~k<1O6w6XOfw zYvb#-9~du+FEdT!U!2{!m)yo*H_0u9iT@g}kH2n8V+)PHWch1MiTDyxyZC`P6CY<~ zVS5d6I-XgjF8*sFRA&vlQ;u&S%of(ux9~@Lxp-h)8dq%pRa0qVj?%yM*H}LOv!L-} zN_e7#S{ZEoi{G(rd>H;OZF>bQwmtqjkckzk zI6fK8>!#WHhc%a7f6eccU0?k-JO5fv@BFPWbklupWw7aQXV@lQg&MolZ=lXvO{b+Ok)YNAa>?>MR;udRHKA19~Vz7gjo=NU(kG3_&+6{$x3L) z{mNgMp4L_+|19qD$|hZWd((cn7nU;@`Bv1-t!YV%`5fSW$j7^$d|J7~_@vz7e0Fn3 zxuad=j^R`6j^)$V{fJMIJI)=C{scZL_iudKxs&*PmzoH6nXym zpJE+;k#Fr=lk;tS8@IP_>)Wzl7(RXwy-^q7!`}jTl9_)Aao!Rf= zyRg5f-;@1){l0EL{{#O6{vY5E;C~O_!|m>S`kwqh+#k;WBmI%QCpg+4&HrQlvHU;I zAIJX_{0aO&(Vxiwll)0MkMHGsVUwgcvl{mGeS9DGPw}U?PQI`2>-P7jddiIdvHvmq z|Kb0G{nPwu?4Rw=#?s0!{4d;Y{u-X?NB&xWEmwG*zm7B9;BRo=-{^02t^G~@Cc@n8 zZ|2zF`ri`r7JmyNf9HS4{;mF2*VfnPL+`yM^xm6Nq=R$;=^}^<7DTYkgs5Oe0TC-IV!47+)EiMz zVnf);_j}IS4FUDO_j~{PzD#y^_Uzf2Q=apj-&0p!CRya=@^Z9!wY(b7cgc65g=^$B z`0f^Yi=@a~<*ibjyj|Xo=lkUQ(3hRaAL5Yjhh;rpegJtx9P)#(sK?8@kT1j`@0NGt z{1N#P^!HKuQ7K4%Tz(wS`*=o>{qlZX`E?nYbL1oP5wz#1d=xD|CLeh61 zFC#yvd_lf|K3Id8J&5^Y7&EaDGX?g!Av^?{WTv z`~%LRE5-R``7+Lbl7GVa&+^YWzan43d6is+Ui>Qmis#?u-!Wo;$bVq0uF6+&{-^vW z&acVWaDH9Bj&q;v!?`J&IIotgB}D=2km9g#8O~)z#yS3Qt|}_d!;~;QM=Ft0m||D# zcurQ5rAQ?O*4KC?RY}FUOL5`ct+;WX28(OF;!!*}Plu&7Udd20aJ6DsQj?Wtu!$xs z9h8pP3z%e8T7#np{%)K(!4I8*;#*#CE~gz^^VblsNj3H9Jv|b@ukg!w;K@xe97HY8^Lvar0L-^gtX`BglV* z@Jfkjec%Z6g8FjfkNOZes5IPvP+u&#dt%K)!}sVxf8sT89eTa_@z=WiYybFkV@CeI zN-&DWgP!UBYOP109sDEAW!z1VFci~+{({iEzk3h{3_*Ws?pe))z9D)_D4)hcln}kp zjQ=-(H}Il{tJB|&5~4Ffk%2Ptj%rcefW#NVN0)jY&d+FW=ueD=IHxj|pNjeQ%O$)d z9G}#FFTU~r>hsOBS-X{ixxY~s7`GcGH=kKCr-By6Op5jX*E`f6$s1RQ!fFB5n z?dWabapQ`jZs4u~E)cku>^~87F5Xbf1hof)BMJ$LUIT6WZ(nca3V(es?sxNQuD!D9 zT#T=H74HKpnAXFs4>1R{lEvf3iW2v_^*J8<2>pfPaPnt*4g85S`b?H4VSgYE5=kix zIUVbvtUlxoE2NE<7_s({A7Z)ukig}KM92^QAQh0z;Nmia8xq4XDGj+A?~*bgE8Hh# zLmqet5(-HIC6EK2!Bw6G`tJhl|E|;vDE>pp7lhqM0J(oDjRXd-lqPfhJ(c6{X&iq~ z=lJ_Jj=yi`_p2hL^Y>vP0;P`tE@OQX07YN%aE#Vk?CCAXKIEG%$GFhf{ z7st?RIEG%!2t%*q82WCGq1ST^y@6xsjT}R7;uv}}Fm!8a3+oI_d_Nn5T#F9^8BdaS zv8h17j{*VDllF3St8;W~0Nvgxm2+HM!Bzs%KFbm9^BmD0N*5T5J9Ic)LTAe0+%n|CR9HD*>|of9H?};^d<1<8tEJ`=vL_>N1xvS zeeRaN1+sipLJT2rps_y*jWLh>yP~pm!cQ!p@DuYAeqsf{ zPZ_L`@DOW3c!-q{9%5}cvIqe+HIZ1`_Fem8FXJn}x*D`7;Zu3?gmELJh#6BxP3I_v z@ox|wk+G5@{O@f1TTE^Q8R8Y`3uT_NP+6obR+cDtDod4R%5r6evQk;4tX9@2Yt<;_ zqVl!!i}I`ToASHzhjLZUb;dm9tD>yFTcp1k_ zI9|l@0**sC4&rzo$Fn#pa2&uEvA<9J4S8pl&Op2YD4j{P|H;dmU!UL23%*n{Iy z9FO357{^06cH`KE<3SuVaomq%Cyx7YoWrpL$95d|;@F1c9voY7Y{9V^$0lVXjtw~0 z?p9CPXbA8Lu&Z4bVZ!1+o6=POM(U+FA80>07%eB}kHzw|PA%2?E`5C^NKL_~RVL%^-Eqdi zt0YNLpJBg%<4TtMEYPa6RPm~OAdL-dFsOyUuO#_$Psue1r!IOweeUfu!1;o!eVSzA zeb8LFk4s{^dVprtCKeq7FDlhPvzcf=popTf_QAcKxa!8U0L-z#We4wn|e;%*%VAzSHVTOH>L=X_>Mjx> zEjz7a+VHe78E<_h{dVMJe`WkfjU&G2$UcIM!JM^ACs~cA*n)jOPef!Nt<^*$yIoKRv_BLDkzVw~- zo$-C)``q`5?`hvt7hk)$;$pjt*%v;&ka;2Pg8PE&Ldu1h3(gC+3y~Ls&i{D+^YbUq zKXv|z^N*kJdA`m0R_7aiHSB!$x$1L+znpZg=eZu|I-YBHuJ~N?IqjTsW|wDT*yBNy z)Z3I5WAqW%^0%SoEauL8;Hefdg za9%XMH@gHO1jVj zV3I~sk<=KtqzSM^GiW_qfJ>A}t)$jc8>y|-4*a46&`Kwul`c|Opq1|65Q4Fql(4Ae3d{AD;W$Vh1vI<*@3Wvz5Kw3_!xyQMuqFONx&OMAg#fa_Ioj%=6G^9s~zEB)tM2^s01NDUoJ^6OEH5LAIX<9(B7kMJbi$NRySZ z;79i>qoi5NIAy#vL7J-!Rfa3W*!{|AX)0Fr3TeOelC(@3BTZLEvbM??#&#ok;CA$IoAjWx3q15!)|U;GX0ZNj04tRiutBVh^@G)BxSu;6LG5z% z?`7y@-<7@CUX*^o`8BB;m@5RMbWS>qk%9F=mvVF|s*7H)XQ|$K zc9|}DTE^*Gc4_l6Ube8zbxLPZxpDP%mgD+d56iBv%Q;Qs@vn9S9&J#-Lgc~EA=J*P?qR%>z3?Nz5VPm{y|w8u4l;!A3U(WuH_hM zY&GugT0MAhqAuYw)*K_97nRf$1?4#GuHwAHICuJ6*7j7}bxu4Z=DrJkj0 z#;h6PqLapnZg*MY8vd@gct+~871HRM=ZR_W68`_6zkvSgMY5&bVuF@`j65Tp0D_w&Qb@Ht7xYl%9;~7CMq3+N# zwZ}%&;J`H4sRMN4xTOPVsHeSW#KhsXdqQ80%0VaAtfFD-JleCys=IoYHcLE=Poi@U zNF}VKb!*n;pbZO)KU3v?Xt`@m?^4f5wBFM?5iiWs8Y5rQyR;m9pv|b(<;=zKqPs@v z@ne#BOL0YKj*e1{3!dr|_rd-QE+2^N`6t?#O~15VqCn?>s0Js`+Zea zRo{KbE-A;ZH>K;YP#%?c;tkrDLFmXYe<&L1JSW@iRrQV6&96$q}WnY=_3n1(t<<6@e$KOX9=e( z;%!n48X9jiVlbXg{th<@$v#lxj0(;^5af&r%C4}AT9}O>QNtQUHLPlIw(hi1Zz{t0 z2Zozv>x~j#Xz}AO10-j5$O|pL{iTpj^aR@hIl&s0eL&&Q8a?B-2ZG~+a1vuX5E2uL z6Q}J!xHAmZZ2Z~IpQGuS>csLo_*NYM7Ot5XxK2{wI>}V$KuVxyDwQiGHd&#b+w3$n zNy#axxwri3B?+LRs6uy?2M@2}rH9kQAD$>EgrkbQQJ!YZ(xi&nyYKD(RrklcpZu}O znQLA5c0Gs3v2#t%vHKom#k<&Ub2vSAna3YA$FlqAfpS6fbF1sC&9t4^7xzfz*_cti z4(3IzEYG&kh-TLd&MvnT5k-5ABoy0|sMziZ29@UK=@F-mRFJ6TI&C-P=t@1+X4oz`Hcz-GP817VL_uJEQAym$vg#_o;1xF9TS_v zoY9)q=_$-*bLC6xCfz=7+R9U>-qLqHeOOj5O&>FH?8FVHKKSV1u8K@oAba2F>PwcpEXRO9K>Zl4rdYvz zyo`pH%5oJWWW-r2D;lR~tKr#3W1QMU`KjGf$@FHNS44=Bh_D&a7$ZTsdXUX<;a#ry zEZ1ff;9VX5&S;JyijJV6QIoJ>ij9I?yh%>aPQe?=Xqb)BOD)zL+x4VkBMxI|B&QV9 zAYoj*`7y~XTJxl37V!aV&cpyku~?SzA3h(wXT!!ld)9A!Y+t9gtvhsT-KJw}`S?O# zG3)!-djAJqTDNc8sZE=XYL{+Ho_g}mZcCncVo6C^X{&Cn1`cd>Jz2fI0UB$U}CqhO7x^ zQ)!@;G@D+Z=u3+NFU&LQ<0Xv`lMx0c7RE=@aM~)3rWmgJX&4iwSTC?w1gB=ywPB$2 zFo%&;r?^;;wj1_DygD6v9EL9=5d#*Vgn}abvyv7TSGR#6F%T6eEes(jDU!jYS?C2x z#ai825zLd8E=IJ7StD2!2(Ad9^TBPga&@Qn?-;v|j~FtZ<<_bHPM0o+W%I{gyMJhi?N@f--=9|Wn`W%pRTZoC1V2(Sct2H78Cm{ip}yWMX{K=ENfO# zd+(2yee$>7A2+YrxNhxs`SPQEuA0?-_I7%6>_=~pf>Q^>-oII`r#>fz0^jQraF^F$ zVU^f80RxEhNg-f}FwNtXDZ~WB^7N3?x}0wWgZ-)b<-sBJS+Et=LW1cuL<-I}!u`YQ z#^&mFy6ql&Tej$Xw!mEez1-$3yT_b#*6hIy!IK-A_+@QqEG>{;(1r?`Z{7^Vud~yJ z8eM5v(My$}fQ5RQ2=a6)joM${i7&Q#<9(AmqcG_~IT)7Dcd_cy=sE^dE9t>>HP4X1 zWt4aV1q58gPUCz~?k)!(Jxb%S15azA^H3l;aRkKC2|mcC6S@RP5x^yYDE>biNBc|P5`=h1uE*PHk3*^G7{N8>J|T^2%RD)AYGu=m@IlPL)E<}XRH-LlEBLdidXmOs25?hDTr&akS9t{W zG!#9BQ8?R(!AT6iN=yP#QzC&NBOas#1cdcsXt<3QMYqwyK~hl~okm6Aj!F15Djr*< z5*os{%24bSdStO4V=vdFC=_9MGBG;D#H=h9WLHR>Obm`^hJ~@uKe)7PoB6IR&%WM| z9iP^J{D|A;TvDwsGUco1=70LEx!dykUO8gf{_aC&ZJs7*a}wq)8-1yV_>1y7)E5E^ zmO9id3quQ&s9Vt}i{?lnIxaZ7B0Q{45_ZM#AdFr%pH{*OvH7}eGvaU-hZW4>0mlY* zV)j54Mhx8OXtpi_~F^(r%xQYv{Kes=vyEEK4rwT+2)mx z4}(aSXoD9n8@FKItFtE#yJJ?Vw)esZZ;sxZmt!nEaq%-w&#f@W#E(NDL6l16K}0zO zzAHjPgIIXBu6T_QmG}tLZFzdoX+4aidN2;aW*R)J1%nr4rPCnr7=lrf5gLMyO2s;} z>k%}a4B*`90g1Vb-1aPMD|z_Ug9oqpc74m{X|e26<>&tTEcfq}7QFb978+;aUNvpHC><)r*p_r@#k{ppB zcG;FJ0OT++)~qPdC$#rPjU3Ks8Pl>_zBqr>?X&0IHhM(N$-au@dn+gVj*f4i|M7>z z=I?Bt#X5GzeXE!4DrsR?ay~TgPOZme)4cepdF6dRAG6T!V!r0Gq$yH)9Q8Z}RLS`Z zmS2SBSP6?a7r_knz z>ZhDDuO6zZJgfe2)Vw5?I ztB+C6ayx@D%2`BT4frU>VU#sm;psSuvl%HEV+T$hHa(1r>*2g!o)L!OZ-|f5<9O5b zdiDd(M0YSvLJDy?iBF8-kg)c%>_()5*ZK}4OyjHnW&~#qEOr0>z&T*;xfrr#(ZqSz z-+ArV*<buNgaibNxBP`c9eJZ}=>>boqp> z%2`EIKCdF$lBG>-s&ZNR3RGsrzRA%`Fz{8LVF>{#1?Bm5ERc_#43AC9(CZH?L)p|5 zC)nd}y+zjm#+5q49`-Zcv#2nmCCkddotMZ%94yNBh%&t6<@2(pp1EwUdrjOk4}I9p z=PiYHYLZNhB9l@L)@WC59HKDsa<=59gytHL{adH(a znc98ugb{sae#hK@s9npCpMGWWX9M#G4%je%NY}M}M@$-2cI^d#Fj*R8Hr0+;HUi1C zfhM>-nDanLtC4h4WU15}<{97mCmfbAKFwRuF2HKe_+5lbx+ z6=cbc^H@;5OJd>!aDph#hzB{?DIVRl-4^`K*IlN><*gaKVuK^D^0BF_dMXxgP(k(` z8-i@+o903DJ#$l}1Fou#22_+}wt0V)xzHRauL^0_uIcD3#_GowB+XvH&a%hl5Hs2w z@TvJ`-)=p7Ts{g7Vxxjas_*47UC-=?FYA3~dvmL~#T;D6y|i8)t75mWSktg&kS$DB zf)*29u1)h@pMHQXeo?dNfA(a3%_rqlxdlj@)~xyt?iB%hiJNvstdVRZ5}b)+ zTsJsVe4HfXmho2HGL7@=NbuwMd_7VSb|~J3+H?zX>SUZJV?lybdqC?^$!Jm#CNnM) zC!xi9yq$JMHwh_R8Je#Wc?({gfr%m&j>lan&a&aRaOP)bn=)eEz2-09n+I9PMXOiN z4L4t5>TS!`EdS1;AAe)`eRX1wE`Rsq*Jn(bx>S93(#XjZXq`_1zded|>w)d1+)aJr zu-Z*nieRmi$Z8w9Pv&9WX1Oy>$N;yg9XeHDd#a9%zoxSMaPT(%_Fs@m!+H+49c1n?Fa7xAGw;3k%#Rk`e9Zjm zjCt97{PiDR`10TnG=_BF9Nae))-FL8!MH0SSVIL}SOh5o>vK{BP7Fo^NZjS3a4=AX z9+EHQUcay_1YHt#-Oe4#I^Q_CiSG^4O&>AG95KDG6a9<(Hs}2<5%;}u&mee*f)<15 zo zL|O)aM<*%3Q}HQ8OYw>5Ib^jENaX>tDOY3MoX;nMbo7*BBNF_cuU3H#|Av5y>{tkP zO$Fnc%3Ax(^=p)GcWk)#&}%zqt@fDj%jwO`t0zs-QukXfiD2M2AT@YB&}&VAIq96Xkm09 zYlBc&kS%~z77#e>JF4WhRaL%O7Tvc*Uh-#8c}iehpTb09Ucq79wdU|2bOgBCQ&q&7 z#GEumhSZPnU5YFbvN4w@BWP^7JV{WJ6TJhn36`f{HbJ9_=#3!K^+aHq21B~g9kf{l zL_ge#^q*Oog#}IJOLt5hHup;P+n+3&%kI+_+_7Cj?FJHiP= z^Dzs)F=p`DrZH1OF=i2b`GxZ_Ga?B+D`B`ZI30vE!v8d8UgnMsW^U%es10MEv1G+} zR_NGh^d34Lm|&68?q*}D`0c7g?3|T z@PJxE!a>8Fabt@ija3%&FspqBLOUMT5D(m_N;9YJHOFI{xwcy!{%21$hFz;vv*l|P zNeq7Cr$K)^YSCbA!UNT*{#JnGj8GCCWiCt6RzfW?6o4i^tgHw_%iB;Tuh2k?^XcB- z%4#fb9xq=b%rgOcdcxkMr?1f~1qbv>!I;4RQmy;+34h$Ls*3&f1 zU(9Rf!KxQ_?|tp{#~wN)_rnJvY`D4G{LTE+{MCGj4P&7PFMW521wHrOchC9x`w7fX z2q?aFt<_?Hw^sy*aykR&tjlFhDfO1@@Z+P9|cvPlyJMMA)H)BRSs)1+hp*EKCqwCb47x$4bO@$p?|^&I!1= z0wVCOL)o(FCl7zxZg<|!W$^fPa1I`Zp1~$c{fQ@P1d>VQNXB#1kQ0)Dfh8u^=^-&4 zG9{+KFWtL$uwScK$gJt}r?@iytP^wRH1piAn^!JhWttZKi+65&q+yo6bZ*H!SFC$o z`&rYM`yN$Nr_Y$W5bI_P_NcX(m--U+sK3*%kui>2;*#vd50ao?t8IzPA!O#a#NDvB z8P3>zVQ~ve<$AO<(xd4acHM(+l8x;^gfk-tWwrRH-@=yejk#&V@>|%TIwQ_HM*i;E zrFU+)^U+JyEbfa->+h1k+p&25ip~4J{>i-f?b$uM+0)vx6;p-`nwi_`qy73twrHNA zS+yCfXAbT=rD4gLC!hUv_KbJQSC~OdEvcI^kKF365g~H?0i~<1KyL#HnPojV5a!~_!eC7UlYfxS$tDv@PU%FPjSCUaADEU&{(y{Km8o1jkmA&XJ7e&Cgxl$CZ65lzqx!=xrgPL>zwM^^D7#czGzw!wwr- z63Q)y73qMYg@tp$?|DVFXrW=@5%iA!AOK>UL0>{5d0$92kcrA*)5gByjY4neNS3NU z)tK`%i`7mu$$adLc}6q8I7|FpjlcGdngA9bcI_8FkNKbzpjcqlO#f;R@^XO8cet=T zAtI3$(omrq$KHXxIPjm(-ZD#A3Q&}nxp4M@`Gt8D;QXxoq3;_x!I$exlRZ8J<}&aT zN&OA?34)JUxs^Di98oFePQefc!#Z@Dqwf%mpJwGflMERrh9!v03v^coVoZR6dKivK z(|QE}pqYI1dN)&%d4L3izF1PrIDO;>_H584$E5%QL?qll!>|%NV#S6^^r%t43K?Ld zlewLx@^N2F<(#ibzOY^GcVzRmNBwwUx%rZuq^-xADwN>8f`)M|icG2};lW~!mqOri z0SgwE7TJX89ehsw%L(Y+1EuqFwtdeY^CjztuUy^tGRDRU`_2foS%E$W5~%ZgdHDC( zWj>;D3o~D0kMVo9;P;epPbJS#{r9w<#&WLE{5P^03@eUdZQBAjM_qCASZw!z#qO}Z zd&zBKl{Vm&KXO3=xJRMdDLJpVW zRMh7dR%&c8tY>}$YZ3f3+Q}^X;9Hh|YvynGzKma#x}?f#ckD{J@S78sZZ4ie9a6YX}}g_%_=A?DB}7j zaJN|OXMQCMXLUt|P-FM`p2Y2EHwUB^9re~V6oo9>3RPUEr!di5n*@}(7T(TH3z=C~_%HhfWU@UhsmfnBGht68+N1t+$8?ma%fr)E(%PnyaK19Ym~m=ChWifx1DLk-M_ z%I8B3x_LgtWa!rXn)!%x5Z?v2*F)^k;z@>+z$(;vD$NJCkifb?+B-~(hf`WWMQ!Jr zI%l7=Cra0PtBxfXY#nj@Y}Jf~-6o}_P42v4HoNM?#@D<tk0r9QVYykT8!mvs#IRTkiS`=Sm`BKRP~9fv>)|$T zQYErV2YDrh+Z`3wFpDjgkWz@E5;vBjbj(eNp;>rs4OGHKz!!jsJ0K!lhPu76CE zU~m;0_daapiVv9l`B%PCvbuc5s7)<;w0LL559Y5@waoU8m@w>iS*`QqefODF=ayMk zJl3H8u11|%Hd|zg8h__q=oEvkRgyo~>ch?g%VG@84nuErJACUjXs^)pJVPV24m)ZL z_eFs5O1I_L@|!DtD2*ct2XIihF znAD@ki4#@I%8Eq?UJngp0ZMm`#`gc8iH|8hL`nHzwX=(@(GtP?$M!O zb7-<4raIKr96t2Wqmarx7PupwQxHiyK{hM~`1xQGQfLpi0gHp99Z;jg;Y0{=gQ!R{ zqA@|V?g7s2T+J8<23O}65-S2s15*8ai-@1x2A(}JVv9HKEz|s=$Mc=DTI}e#e4cmh zz~g7H%v{)gk~?iumxTe!>(l-2Yj1pTv3|y@sh-5PLQ(&v+?DM9a0-3ZBdwCev zQWQMJ`St>6DR^2W@w7;q1;NvV9*_6{cp6lYP-5{lL|TndQa)257|-t=t58r znNq?q5gY_SlSeuR+V=6{-+hT~DzH6lgo~-#c(tL_l z^bQ}wQv!>P<{D;h!%hkl^b<4vgo&yU_ux)yQMggh2z$P>MTe>v9!qa> ztjZkxy2aXWpgQ;3ssl%Yw5kt3q_uD-#B{csZQV#L8=nI zb-(}$g$K!ZKsemmsSrP^rKu5$nme!bVHqshyqn!`er-NKP>Z|1oIPkp_ztqq%q(<` z)f&qraqoXtac!*9;;#N1-&q1IJ`3w2L%L0T$FL=lK898UZFPE>*T6c_oe*#`c~jvY zX~@_QGHl%2B?&E0;$D@84WDFzIxa35MLX4#Y)+ZUaUD12zlzL%>;j_Q7Un%d<4K0{8P@ePxAEt=T0;QGGJp0Dr z^Q3A1ZCrvz1LeQ-!0W92OhwiAx zkbMIs4BhBWI#!jxdH_cWoyVo6jqgx{61sO<_GhN7HE%&Y`njf!*&mIXe+-ns*Q9(9 zeTbB5Yz~3tXoQe+8$5J`l9ULRq+%md47p^45V(Zd9m-xmTlOz8YZj2CeaTr{-8=in zWZII)cNmtSHhG}WP^;yF+N{WDBRYVr2Ym8A?p+@{g<4{=UL*7#8iEl;U@UR^SH z$hcw4Uw!MFmtF_TtQcGsROufN`;L3E})A+=xb${j#6 z%xYe(@a=C?Y}Lx`Q4c&W_ZRatA2Lda+5~*9uUM@@MGBZD8cPZzv4h{NFd~2CaJVG{ zlF>%aRY!m)a8Dy6g+>dNdvejfNBEtqw1v1e|H{B&rFW!NeGrrXz__Q6ve)Ffz7;!X zv}~qCTzg~pfT3UW@q-BaE80~{mqfcrEnO1OY(SR;YcZjUzttsqqo7M7(cN|Jj6;k1 z5t}>vvI*EHl60LHl0ij3YtGq^!RHHTO^uvamv_{E(tPQw0JC3ymI?WNH}0^v2L-$ zeMd4Zq&XKlKFkZ0Vw__AempG^UmW~ioc03?F-x-V-;mPIl^EV2taXq0I_UYF$?`AP z(r()w7W5KR2R0ok=oda=%27@yH|dm!x%{^}rG9dnuTtp@t3m5s@+U{{^QHN9N{!9! z@+Pf0A}t#T&m5Aa;1mNNHQ>l-FejMO$^9jo^ba<4k9zE1ndFuPrwlAf3Qq_q(cvsd z+iT;I!}c6$FtS(w0R#H?8rk5;o?)`ReCEWrpSWDK&i(j;x5qzJKkuQjZ!dV!N_mNM&4u%MjUwK&OC*GuGV3)8-ZJm8-4!_Y%>MS%H4U<{2^m zekiA5%Qh0x5A46xk3>?q(Iy3%RX|5DeclbxY?>!7k2}fX54}np(Wh+4kg`4_8od74 z(9xrZKKA;*sQD9i=VU)LiJHHz=<*Y9Pn=mkbNt&+{8R*5n#Go>UnqHyTl-1`or6Ov zK|qE=z8?uhNVOuP!r;3dF5KPWePo2e3D{6<1O$R@&;d!&@t`dDis0NDCaic-JRk(2 zF{Cnx<%k<>AIcBstS49XzqePN=?451zwrSg--jvR<_nvCi zAvb4SN1`iP+F-6>OF>s8PeA+1#cGxI%zu_607keRu>o>~xkfp9y_tIK(k1k{S9Pdz z!ICMZ!P^S-Q{fEfy2psT3JX6A2`bq&H(zvG;v_N`jzL5a1jQJv=Jq6Yc zBZA{#C!Hp{u*4$Zcomnx7aJ54aNiW_6cIS&6n-3h_P91BhKCMi%Dp~3`sTXFF9wt; zXJqBcm2V#X5XzKOtX|UDZ_-X}tx={}79LN#{7oW*piX?D7clW8*l^M);x&o(xMY|x z;`7TjvfV@gEk$qxMg;tP5iOUb!9Uo6%@38LAqGGzfq)6XzjB3}coYcjkYIee41U)49Uy0$ODf4`2G){m1`5m zESvq~(c5}&Z}R%<;l|Lpf=-51e{JcZ{tVq`o-|hy0X~Tyuh+=3R_gVkq9P#e#lyWmRam5$HP}P)K3qRTY&R5cvKAHxw)T1z>ZL1vqwlE zfMBm-gA-n8enqsC7XS`LqreJ^h^0U~Vn*b45R_jY&fO!z5n}?vFOLW(X*Yr>z?RQd zqu~?@AY+UW7!feHkd%ulrUQ5yW&=7Bu(PygZD5y}!J^Fv*eLUXDsv|rgGZ|H^YAs= zvSG9N9?RdnVGFJQ)!?;LIIp#WzW)-g3Z6+i1O)p8%m-NeSpTcP{`zb4ijsK!YvoP( zHy<`jTx+PAuCBv6@gm9|(TCh=nEYhz9M{-usnQs(e1nT4q4`MP) z7ubwkuz?6LYP^F7rpu-$&=P5mx6Shm@?r0Q#Q;B4hn_`oVTO_q?wAWJZwdS{V?Ego zi<^|R0l65i=2$3k@buCX$bbz`+ibhzIW5eUS*HnA0N?OC79)m0tywvKgJ{6DEiJvJ zEL5``TEqJmY!~DwkT$4p=z!jBTC=Eceq>?DQn+s6(&h7x{_=HM?>24C%io?i-?PY- z`{&JDxAMg+Utd}9dSQE4QM1)A*6W^8R4AtmT$hu-cErB-zC59gSvjU#|NaH74?R6( zO}+dzBc6HVts-aMyM}NL@MZNeA{;(SifZxS=%TeI1 zSXi2#5q8dsNFFQA9cU|@{Jg@O9Sq;+3a>@#tY(*Idx>_l^S}s`()kBT;)8UqZBBQQ z2+)Y{e+cNMNNeD0@O_Gqq<3}1^t=dkYj11SSjU3-^+Krw(lh`di(&=QR>KQ})$ zN6upde*J|FF!%lPo4Nno%ex;iRC(*bfkVfP89K0RtE}n|?0#AP3@-G#+0#4*!$Nmf z&YGEjnD?>?aO$$Mapn&5fs@7Lk%?q~oP-UWLNP*soo!a0?e+w~cF!)Wm%776BVbx9TR{Y8W|}XW7d`Z3rBt z_!%A?MCIHVg8t+T9%_cCft_)$!s)p-@|t`EpFX$57YLqTlqj( zgb@^?xTkf$W9c(ZntCTWR(I~BY@asA+oDxLUbr@L>H3xC8{X1-&b)-Y=JTdz*KgvP zP=db0uY80wQ@KOgV#`!I{d&e`RXVY@$ezrk#cVdR6=lG8ss@WfEl5Nqaq-a~tYss6 zDwW<8tVNt~vC`&EdEOIdFQyWo{@=&UsW+{Gd_)Mp`p>HXCTUs)4J}f0tb&Go6*Pn^ z2Y6dWLR0=(0{<)!JA5EaXk1S@x{f8E|cF4 z@h@oZxywJC;>#mRVhYBI6(?L90VsZBGHMMl%qoThu7HsFxlWG8m5lTPdc*Y@9HVvs z%Ho|(LzKN8| zBrdoDCi(+Yp*Q~Lz*H!){DG-ZNBm=8DwJDdFtAArXuvQq!`RqQh>v|@9#Y!KM~<^4 z=91&)EVkB{N#UUw=i8At_+!g);F`e_d?FFtCFB*1)L-Hmu{+n2UU*a^ARlDJ{}956 z4Vwe?Kv+cNUji6!*Ph(8cISvWcgk$2?;+N(q>i^y^O9%P_s4BoI;+?02~)LAo0!z7 zechbK%^L7FkC!*dmn?6D1c6%PENLdU1Atn(q`XGaVTPm%NnNz+EoxnpY4p!m39ZKp5b z_?t-!;JeV1`!3YuF~sa2d>0IbwgFj0(?b6d%ND%KqGa>3dXa@_=5?Cu&Cp$^ay`e* zy0C!yI)v0JaKi9wJjnP6lNR!D055PSDpGm`6BLCe42IKyCd`O{Nfjdl(z{g`mSx|3 zW%P&v(~_&cwAR0)OY>2gq?`6_-8-jwGsSW3jsAs=5|d0sHBkE~xM4chdixZfBp zU#5q0+@SI(XUfn5M|mE+YpZ~mP3ce&6Af9K=pWHjv>9N_Z^4vG*1oDwrRh_?c%NC| z=o|!CMEBW^sLIVsYoHx}JastYssAY$nhaXIugJZB`iXycirI>tz&9h2^#GnjMhMmm zg=7;?!b%N?BN1dDQZ};$UE3J@G}djUHC=??)D#dL<(OXz*-)*#BGbceo9`9w#(8T z@&P3W*CLxr3q(cJ%0aRVjIY77TX2g?#ouMO_-nlOf5<#>$4d`B`0`5+?0Wf`(tf>5 z%lh;kpt4z8Uwm=vta}a}x~Jc`as6iX89%-cngl#BQMy-It2_rh&^ZS2XG&*e%%pN1 zI?FFDM{QYZm{cZjw`D0^S)3GPv#LSz3;3$PjwVqZe3pUF0(Grwh?4EEGY59N`z^Pon)IF`QzW4I2Sz=*3`5Ai)g| z1{5p?`G|tWtTn-6PRQ$A%Y=z9SMk%yz+EZOS=i!mCP5E{VucJnSSv*kKp;wZBPjO- zl=P%Q_QuB0-a=tw!#Cg7IQ5F$a%#_k<45(HDSxN1Uk`tDiS_>@2r*&}2MyRbZ*Y&h z`iz(~xJ*Ofm};r4#F)7tn_jhcc4R`ML$Q4Aq;J^Zn(|IH<#UivbWlxshd?>&D?P-@ zYRX5|ln+E^M2ZO%*AEYrBPZ)ZHl(I}PN1BXBCr(!!k{zBIu+}g?8|pZ+$9+bRpX|B zln5Js_W;V2Fp5p#r#v;ei1}=7U?Q(|iLbQDE^~I59@IhpIotFsj z&SU2IV`ihHJl-l>UPQU1rkKqrE(!gs!^d?2JB%EHJa$se;o}X35g+fD`FQgf94n2t zD4&DhJ)rRxcP(FuP=q$o$^NgV2tT3+32!oP~5X*DZ5{Vur5!4m z6$LW{l~{vWH^_`fw?d3;w$(h!pWx{~nSNkn8^Y!2$$VuSYh}KQ{boY-Lx_j?5gT3x zavqNHd-~Uf8H>+W8rkRbIg28ncsRsU(gjSC;l*nLDNPXNo@0O33O}0EOcD+vM3f(; zY%-!_!K>2jMoL4xs)**~?zY_TA6^GyyCSI?4meg1lIj5erZVW{NbxLu@F-bF9;9D{ zR1ANjW3R1Cd-SKUiauLg_TRc}@aU>Em&X36KdbFShjwKSE!z89oKp)#S>)%f`J(Un zJ4K*HM*5bseXBNfTiJjqWp%Q@d(L-vQWC{ow3wPrYmxhY^EClGHmwPyK_VU}%4yAs z@;U51zUD+ZtqER^`TdZuIZ;k)Le!ruJXPe+<^pMfW3`pN=VLvbg4#1kmGZ#H5`bKxT~Ejp8fhel|F7As z?dQjO@5^jhcYcc@L(LZ#4Qn}Qn%eHGKc9ci;xx1!(U`z1a zK)L1ZK)Ey-!6r53TBE@AkrDGlcmOF<-|9=+qp<(y0tdFn=$GeU==Dsmkq^B%qzW5h z=@>6XJ?bU-6-^U!ke@?uOqBn3|n;ff@O5mgtj&FlvfW5jxncNl5NwI&()IjHZUPZRA2q_jK=(Kdpb zqL89{berGf@vrJ1u3Nv=0WuJ%EielC5Z8D__Wk+W_lEQzG6{)RuAG>>zj4dQN1y)Q zSE{J%){R`yr(^MnmCN64-SqT5700Ru4Q#Wy?mJWF$-eMPlkly^qCCbgSgGk3}*PBTBsL>a)HL;{tQ7T(Z0qD3>OO zCsBFzek``7mMWD0Drm2I41P_q8ouC?Jjrs!U#>}W5}|rR{TER_*z!}LKK5Z3?Y7ms zQ9jG^T%cT<46#fDZ)t{g+}-j6Y~8u!r4UG>2H#3UA@hoGAr~psj5?qQ_>yr~@j7Yn zZB?vcPD(1LC)te{KuyWW$-qKIwiyMU)WS?gNhQF?;Sg@gDndRzTBNbCp~PUeZ}N=d zEWH`CpY3;Vfg0Ak#QdfEzueujy7b-N`u*L2byi0GGDW&gdL4)lRI;10996&L#_@wj!XvK1zP@N#K# z0eq2ApZjm{bvTq?e-0!?73*pZ^c^kWV@key!*2D}`w#I6FxkRk47>I%{(5l)mHe>@ zBx=}-Z^R~$@`HRd|H)HtO;!HggZ{=*&w9}JRO=4^;Hg*BH|jI>O_L^H6@7ML9bMIa zL%ERkX5g16+M_<-CoL5yr+reBW;EtJ$uGMR&gJ!4f9Vu^GEiSj2-Ii&r%&W#>N0y< zJQlsCewoskm-jJyt2vwp)Ag;aOm4-?dF}=);cFoy&B1RB6TarL6@2{)o;`=bHv;9N zKDCF}$IQRPakr>X>ze9g?!97Ni~5af>JMOdu_b})TfX$yw?bbnNp)+kPx67dem~&) z+XMBXAP-!>UuUsbkPP;nmG+jpykGsKl^hRZJS|PMIFxsya%Ga@vpD{LmYuLJh(?~l zx`+pITy3F>pyx@t@^ajiTVRrJ2nZ|;aJ7;mA^jd6+Zz{kFHPa zimx|Ozl?G0A@wm=P#jE6{W5k@^47G6%0>Nt(uM%NqCF(nbf)&RejUYic+L#o{v7Hr z*4wjuz43StzK?e0_4{@d>rK?Z4c8I%`$N8d4fhrGiC>8N{pU~Q{T20TeTw=6@ayBW zK6!nOk#)3wSoHD8vpgJ$^!6uBLv666&-@Rcw7!)1236k@bG8)gGLsi zMDDn|DF4Rt<;cJRu&~xQOO+pHVdgLNc=(!0**H|0$4JnxDDxPUL}`}D(v1aK9!BdE z0bK#x5!NScN3}DVLPwLpn@$3R8ic0DC(ufar(C89@pPI%y+F1Tl1V8Vfzol>;eN)o zXJMq_C+8x-8Z1MyCehATJJtYQ*;>Vd%s*-cu2iYV_wU`i-~9IG=oJ-OEMQ+mV#*u2 zzDDS#23EHueNFYlD4)UkF~`U?)r{)Kv_5(Lxt86a1A)b7R43v$ zudC@ddgU>kzQy(XS5K$)S^XZ$J97FK*Y985N9qT9s%Q3QZ}as=^)*)Z72qJs!%_Y; z=l9)3`4LgR3o^h{R$9;E`UCK*rIR3YLk95s(beQk!35PfE@Esc5XT>u3S!v6LvX}3 zpMnhOvgpXY#;+;m$)I7hVI%xeAJXDbPHnJCJ>)1}-V}U$m$fC@fDC7}hS@0A3w?an z?1DV^7aW8+u79d_eRi+KLD#4D+_*mY)Dhn)fBl^|>VseZ z?t2Df1=OJCfxm>~x6HU^o2#|SUR9x4!-%(NlynG#7KVH`Pytb*B}8pwH3oB?DQU4` zLx3V1Jfl2}yGn&2(n*){DMtv!?>kn%{t9_qtB9%A*Hm_pv^8BPng3@6@EMb2#U{_CUUW(U*d?LMRX!R}`K z>+*2XFS!n|K`8W|oCdh;<2OJ<_W4@_G@4x_5z(!RoK|qV#Jj3CZK}dO8p>6^Q3VGJ ze9h%4MBf-|@N&}CaosKC^7C9*CuBpC^++}(dA$$EiaX3i%0UyTkGVh3=Xeq57%@wM z`Y7)cn0s8G%K7ynG5Yx4D6UV~kFJlsaVp1t)#osmp?r?{eU(Yo8-ekdw8iXVQ8CAH zu#F4-8YRZ`dx%4V^E+KJJ)Y}wC?h5kVN&i#=yFKaM~PN=;#*|GLDF){!~2Y3sEWN2K!rt83v{kJ{Id;U-1;1(u8rHX^NSTB7 zE<)_42Ax!@gg9or&-O=c!kL|cDT&CWMA8(Ch#tz#OA%@aK_Sa-AP}1;^G8@xti3#3 zgF7;{8D4fU`WlQJ!EcI}LB?h>S_QOzfsn>UXTuxq8oBRff8(3QG;K9$sABy=Y;PXF25;|PMs|8%95wiP?zCxxE^$DZ! z`uN2fjbjvEpUX5<-wLd@PMTPA{oytB2jSQING72A{ki@~)E|Uj?MVcNKn@pcDD0)N z(77)c7=lNE*Q7_ak_DBrx(OXTz(i<-lM;?W8ypA&^iu_;N2P2{@bir13CALVi{a;q zEOzjZG_vq<3R0vRPFV2uNINoMA#PlR{TpdyKIXm$q=Sbdhqh$@1J193WIRRwfT}V0 zp>Cz!`W{MgAXnSh{G7Z4h2AW1AaFXczNsQ>xo zfiE)ud(df*jY|MFgitih*KIa#lpu98W%{q{A-RAYylr;FN?w~@$AQR@C`vDkcpI+& zkc>>yL&wsm7@Qag4fQc5LTC`G4laD(61**Rm;Q9(q~{=eMaGSQ?%;10A8%dq>daeW zx|hGzs@1VYwSxkcxIl zCD?~dE*B3F<@g0Dl8eFXROCPcjq>{7X$v_|n`kCdtQ*RCee84b0bYmeQ#r2>Ubmg| zx;D7}?;KZAeek-sgq+Ls5^*^l@;v9UE4iG`dy=t^a)F-)z*N5D&hRY42 zKFR4+A98wTEXOEg%*K@WC{Q0d+AY<;<2t2gV~Usa*C*X=9xoTyCpleQzaMPSv?j&% ziC2s3_iHZNpN8>4ZXuKxQ#&y}lleHfOgqJ+p}b6#OP`vXaGf;p_RV~Jczuk|Dn34l zUsLLGy}rLb``*$3Jd@W4&yOUFC}sTh`<#Kik?bTqECkkS`Z0lUj=QL<5MsBF)jslU47$!?QHMzyJD=ieoa0ig(qL1<;Th{KD7Gy{I00vMtJ zhLAiH6b2Y#=WNIxNe#0T21(%pP6}^n3Y;ztq|ZipJ~5#C&V@-J5R|99 zxrf5?KK{5?V4hsGe~$>w+q2)iS`(bdkS7XrBW!Rq_f2TdU}HVSZMa;|$7xsS{{{|p z-l)%I0$v|7`@39b7kWXG34~s7MxUQ<)aNpRxPE_T;WE3pKG81Kr~P3qmkC6B$mT2R zm*Q7k51^f*K4E`RzZAc5cEje_rKbKMR>WzG>i4t!Qd55rek)C*{zAq_-m04VWeidU zT_5FMwMk9=G8wurlqXaECobDI7ool2LK~~Q--2k)c@UIA3UpA!yd#iJCb}4@@7Or z_UE{UJeIh5^G1L#ttydq@J0rAzje}|3d3n%d*qq)jydr$*@->+ss}0k#UYC}wC}Z! zSYu}(Lw$sMc*wTyrWionz@G^L$$hwM9Cp26EViV4is<4I@yJ4loCt_rq68QS3`*g7 z|5Fg+Q*PzU%Szg>3~E~pZQ`(=^1U6hwZM6WNR0G%89O+r@Z~og(A@IW;o)&zRbgp z(ufxzXu4L0e1aq7$Rykz{hs%nF$8|TV>I~$EdHd|v{@(j+?V41$7G8Gx<~I_efVl_ ztIgg2A?G6Dv`gySykCequ7P1UEGd82uLB{D6qvh1;g(m^Eft| z8<~I+WH6axv})7#$f7yu)!!u%=+ruK^_b1a>XvNj^*6}`cpf`#vep9Yu!sMb4Q|R~ zhu;u^#~IWIfjoBPkclLcaLA-z$FXCc$nlnkCe!aAF%1xj4D(PvkvKt4Wys6n49w3> ziSD#My-yx~@vrIbD&+XR%THIke2@Fn-eLWLpIN4=FMuB**EA`LMM`ywp{{WmO}VwP zh-st7#z3}!-!dYfaE4}AI7H+Ef&fL!6M2>^YQIK7nQ?qx!ZAO!dI9N3^a37okSw`Q zI5QAttqtyWKvtf5;e)@1ThEb0=FPU0AGKfqkjGv7btRK6-___!`c=2Az6##s0?)e| z)Ec~p+eg$;xaI6YInkVKl~B&@9crlbi8Ko3;pE%Kaorlh3+0m>*Kxl9ZpYm3FJI5? znB0HIx(e61-_JWgVmtWtVIR~~l)vOJ&y`|OKE|}x#!TaTLna%vIoD z&;hY6(A`8rAMDTMQk#EKMh6a7km-)(JOM&#n2=xi?7|sN>npWbj6ZD)-!FD68`(na zUz&pb5p=N=F-XnelN5wF7E(tdE3xc%PloXT{`D5_o@;=sAe|n0j|jk?;kDogT&z1; z&;}NAWW##(V!}^X;?{!AGiffaS>N(At{Ef2`bv>7h^(L_ef%<9uL_4Gr^Pe(eE}cK5f~rHR;^Bi8lYf`}jC)Q$JykTF8cs-&o?I zS5jCYR)LJis#qKF22=335w@_6MW~;A`6aF)OS{$EV8t-P`4Sm5gkGaT!&ng(?)PdH@UZig+efu%l~s^f zH_4M;+I-BiPkXE{YUb_dP0I}nT^|*H8{KD#dRpma`5pJ^A@N*T_*qGt77pgkGwJa( z4HXDxp@1=DpMh6;MF@W_%;SVj*d4;n3I#3l6$t}uwflL4jSAcDK|GMr50kND2n}s z_N$Sm_m1dd>r`>TSXggo|E2WYw@CZNctP)j=kt8Ej5&2Z{f}__<=RJ;1MPp3#a@Bv z82%@GZM5%=ZTb@EpH9_q@%|#K5*n{XoGT8{Frg)ZGNlb7kmVDxe25*@(HyL%+gsNbjvvyoYe1(BT1rL^ZfrKCB2xRdvN7h$j=74n z5w&BWrHwfCHWF5i0P4L$3N1yJ-;Ac=`WD*$$CAF z&OVMA(%GkrF^A=IGfyH?$GsElp|U&L)ziaqR@I@i3R%We7}qqP{JH%1*f;!q2e-cq z3u70zmobwu#$$X>i6m}sZZG|IV=D14-VfEH{lU-W{bh^+|1Hiu9nU|b=ct9v@2})_ zTj|EV_#ypnJm1XE$5uvFK8N-^9y+J!EXU8=@b{>ffuAM+*CrYV&IvzHyHwhIqd-;# z#LMKw%+pTf#D1Q3^0{qNxB5WL4mM&4NufKGooeaQydjSot3ciyX!?juf%B(9riR7M zOs`0<$p%$!f->Z+(x&`PrPSES^*xTNuloB+abTTfOy@oN3Qk%4jJuT_3;V)#ii6@) z*$0YqgD~8wz)YAG_$+HbF7RAQauT7qiMzmZ{9aLvkIH0OUq1de-}>2<6V?#qG#zrRZ_ZP2RV_r=NK~nrYhwfkF!5X< zLGDaq8KUMTh?o4DuD(!lle)d)dF9WeN6Ag&+x5~*_-u0y@Yz_$==XiJAGqIn=6%(y z1ml5yZ!&B!kjx=dvSH$zY4#K_rWy_RX|u|Fvv`0%VWG+KY2cg3XEfo@=z{U|z-NSD zymHm~{m>5j5STqolE*w(qPg4QWIBG+d*39G#*{9Ia=43l+sIeH^bHpqj48?+Tb1@o z+pVwo{)qPdMm}JCw&@eYXTyhvpV@D~eZfA3Y~ii2FF{|N_)R8dG*fLv)>tLsF=1GH z?xX@wcrc|3mZ)+3Afte)Fd+VA@u)^3jRPE{6joPbWmw%~N2W8Sc<@~T$u)eBCVnwo z=Ah(2n`Q&Cwp&Hsn+0GQRriE90BM6K@5Iq_5UJtSZW_iuRb%PEq%) zTmJ|yoFoUVG~%y@Tw3#-kR19z4)L@Pncp*<)|LQMw@LnD-R4jeo2XXlLKnyvIvO{5 z=8#xq^2O>LSCtnzjG@3u*EqV?*(kOK_)_VHBE3|%b5$#7- z{-|m8zwrEC^Lc3H1w1b@Mrk^?-)KH}ar?({<`i+Poz5JbmFh>l7KjVEp}r39d5E8n zZH4GO)mo<#+>kh`ja4Jst3@K0WU36zkKkHNbXB7q|4h_m@+44b zh@2LT#%DN{li*afoIoNynB;ZfLA%hay8eck6N^bMduk5+#0Y z(h_8RifxNASGyJKDjMh39B>-YIS86Yxt_q2U6Pg>L8nj}Ma5<9P@?^a$)|!8#C}9L znk*vxpuj05uVf+SSRA3nF}4}xutB(@#eo-zoM@>|a3x~sY0Q0_YZYv4T)ieJhb2wE zL{4R|maMx)IFFwAeazsw%lovU5PXs)cPRd@B2$(x>;cFTZ8OULkDN;5_A=(fI;2;GJZ0ioNkMicQitt*ak zLf6FNP6i&zXp(mVE`U|s?UD?nq+fFIxs=D@ae&w!#G@tlU_Cm7B5imU z#AOPCfzvD2?IE`YE8=SXK7^fQoKkH@e?>HzyzEMsm=^Pn zNJ|m=g{?2^U-$WA8@t5nmDk|c6mmamH(?dcGkF!$;C@Zxy0mFo@T&$w#2zP}Rk6#I zxDsknbxIdS9p&1hJ;c>1vB^YMjJtL0Ew8;cdHVcY#})mc z*o|MGf8Y3BvA5LT;Z`19GNk>WZhi8f zIkIxy_X>=j)kgm{@2;FYY1Oj1&(`0Yd{gWC`JXuE z1G6Ua2cS{6TnB#(lPuv3_CHrPW{ia{c=Ma`BU+oHsm<~$$h89dgs_RV*+!0qjg0KA znpLWkpq*T?Y$LnK_LJZUnc!&FtR}`&DqC$?%Kxftb!)2SU?x6Iy{dGzQCEC;{qohD zUfgKbujX?GW$VI$^^z>J7G>*1m zX`0->SxB8wHLXp``W^Me#ONF9ghxgMBgi;^W1|DQ>uoJ+amRt0cq$-x*Yt`Bt-5PM zJ)%1l`-3aQTN8bhmuYevU>vxO;^#C>Joq*7^DrLQSfiarHhBZ8Z%esa9s)ZDleP@P z=t4oMvVb&atv;&sthiGJ+*fiiH-e4{ho7aJxtmdTi=%ZCzmAhofKG|dU;^Dl zaNSE7-MoqEIuXma2x7~SHMk^~D6C*jV9T>BV3)vp;pgScWmsX~rcVJmqViHsrmqM%tF$uy7&zAW^Q&`U>Rx=u!i5VLi=~T@ zi1dS~BaU@EHa+HJ<5LTPv*88t0*rZq+%B8?EBaZj4iztD#&YmI{J*F})j>UAJXEI6 zfBEH#6)JQL-p@8a-XBB$I_5y;_#Hk2Z17eJaJBdyA+4E0h03=O3m4^LQsjXmcam1s z(%nsRl-z>Y$e0K!mAkZb-YpAmQ(G2XENFM;k28OXPn6NVojdRTe)nP!CEaQmTM;mQ zu8ilVqmf}>jy_RkSmY9hQfE-JJ`EVaG-gjogW|HZI3=@56M|ycWRIglEbMVwfYe#i z@La42>MVx*vNT=LRzzFDH){~A;jV4R_RX@{>4Mq-1(G^;DEzr;Yh~Sbz3ey9+$b}? zDgzV$Wi?vgwMl(=y{>fJR6c(BU-LJAl%S~djc304-1ujL(MY_TBD!u@VqRFj`2=0C z!3SgX)H-V2fW8C2H^30^`WJX(@h|i9k|F3-X+k-PE+>z|yEab-!Vrf7f*lEo z7_OK7B^ExCG_+-KW{g%y=g?ts*jHdQZQDf?%FDVg?7LQcCX8S;P~6#Z5C#C9in%Dl zTqLtUmwFoDBv(L*pIiaJ%;F3zzJGF zG?+XCIksM9TW;6O^ar-6Z5sdFv;*oEep%)-e!_-7XT&^pEJji1RotZ{e7t%7fSZkN||;0-Rq^4&@C5g~0-kmupIZsE!n@ zxrpdS6M_2<^cN{w7~ovm$XY%C@@YA=;+do@*6E2S??G~;I|1uI9ycMcEg9L%Y<@=; z7U&8Vn2cYWf$ZuVLM8=`=->Hbr{3DANh4;IPaiR9w7qwy(oO^3{dU2@yu5?+zk5e% zx=pAPmK&8t2TpC=B{~_;?b`VHlSM*VHo@?1GcFm=&z?Sgw&=+Igk!kZZ=<{)=}Wdv zu1w<`Mc(6-vn%iQw#hfb8*QDRj10l zH6##anNI!yEP3K;&VW)W7D`YuwgIi2Len9TlLeOy$BW?O1yK^!J}i{D-I&>zAHR3Q zp(k-%&NyEf1=(s*R5bNQ`9Zdn1vU`X|{4gT0vZ# zmKd7R%xQdHYMhEJOb<^`?FT{vr>`;Q_UtL{S~Dv!tF)Si+CEoO^e{WI5v;h!CT8grI&&5*T@G_8!c)BC`+EU76s51g{PBV$;fx?XSQVciE5+E$bkW9ZtN- zz*yR&V~G*SPNYj*2#MXK$UBJPiUBcHEwZNNNoW|#t{~>V2;4zDM3xQYBJm}M!lxmH z1GFXaY$$x+g;Z(jG^OH_-piuk=(7W6P8N^fNeX%i89e@fjC4?}?xQikpLuflHg`ywZSco1Zc+ z0>4*P*EE;BeA#qG0AG{W&K!DN=b7u8qC~4Vp5dhNY;M#d;$xyMaNB5kQ(aS#Tu|MM z*nAHW8${ip+v$_{*Bs@Y0a6OO>LsY8Ev8 zQ6z$+w|YfWPfWONopQ6FLlDsl=zuj&9tU`J zAi28ka3mOFje|Cc3B)7ecL+$efi+y#Mu)|0|HuQUh}X`g1np9NFxZRSc(@Kgfsn71 zXk{3jn@T+32ZPa*EV4{|<>~I>Tw>qAYi;Q{$ab6=TqH;VLJ1lKhU#y3k{BATpNvu1?>H=1vgGTHaWZ^vJ| zq}=XX^5)%>Cai_@J0mvpE9N80HqgulMLjR-xnJ!>M6%kUPD}PNy1PK_IQc&7B(+mB z1+-eBFTTcLud#}OUSV#lOlN0OFMnMYL1jzt{Yz?=)8Ae+g2W%&=2!fs{UmiKV&NB| zBN6jtoibUdc)kVwbr1$uATEsOouIG?bDRfz;akEqi}%=$7zjS2CosNyjjeVS<6~bm z`L_t9j;Vl)gVazk*wU0J`y&myA9X;m?sIsZkdAyA{UDyCK4xSx6y0D^Bf?%{mn2Ed@+L`=$ny_5qf`Jo z8cN3?Vt(*!u};VGFxisWnv#&n zHP%_>#{xi}tkbFgq|>p^GmUNb&(Z%d^dC7tR7RUNEv#I`B1J?=SQs--1_E$TiwAp{ zFM7~!Gz@f{4kMiEAX$n4aEXp341u!w+McbL!}U|_sJg2iu_I&tQkXmH28kC9Wl%B@On2_#A z#f_qm(!V^?_lX#1Y*T7$b&Y9X8-!u!Gn(fKXED}G1hD0&FwPi?U66J{wHwqkQ)p0n zP(eY77Hv}yxrNTsV6X+iyuoZCB^q3Nv@vjH;i=K+G!pRtVZ9JFJuMm}g34NKAmS7e z;tQiAc!DQ%ENu&GINRtVJ~Q4o?&((A+qheGD3AMgDr5O;P{k!>p>H{Tp^NAfaXyf3 zT*tPd?ZNO8$3Bu*_rRhzzWoStVcmea3x-zn2GCxoJYCYlMBXYx zPo~>}076)e9B(3qSgL}Kn2sIhksU<0R$XOGnhR5x>C6>dN_FL~vNGMb0DJu>MT-H* zB3daw@7GDBdsrtS-!7i>DX_LU&)C9k;Ot}kLpZUF(%Nzd@X05SJw4&M~i@ zvtjwH14$Y&&61;C;#2*n8ZCVowhd~no}#``X4Lww;wX65J1D!+IrFTNYy3JGkovs$ zYv44{-o$BO@58NV?h!x60zWh72y&Tp;t;{l8PIK%d&D>hjEi+K?;+$RP_B@Nsvht} z$htvti#Q4S53AjdgipZev0|wHH}(p0_xzcYZABi=;M4*gX!#J|FD)OxzwLzjNwxZB z_8p#>fmZ#jDB0C8LIdS)o*<$B6~1TY%CiEKeECW-Ul!%UWNyY*YWI`j(aT zJUGIKiWJ|8w~QuRXSrgOePH@+9}~;5ALQ@?r~L%W0GQzFGT;Nr9!UO}8au`uI{C#I zT_-nBjpML@GIKLZl~nUMlt-e}SsRT90%qXz!pY9CKF{L-Ly9GJa-mfFaGAnlisI@I zFAfV1z!Xrjq`4;`13C@pi>ATq%JFKQDG&C2BSxb`3Zh>&`&jhHJdZi@@Ex@Bh);PNs&~Y$1*NV7AK#^>CPz2*i@BV>ooR#T4o)`h#mUA z<>MI3SbXL{+a2YWC4@F$jnb1Qu7B4C)7vqS;F}8hps{zuX&gwCoz{C-ME!ZnC;q zqkpoP+*SRP80ml6scUtpW^eGR>u}fnxW-+R?_Ye^Vu-M8piM9pD|hG!OcXyX7rNCTi5_^wIVcuySPHG^>e5vDqVH}jr)9tqU_tadCLXGE;27)7KO$emwm=p;zNDo_VXpJj=4&H z+__Qz9FWw<;Ih16{ATPENbpu{#E)?i=YNbX(`IF~bNRY>ib`Re677%%jAOJKj+93a zq7W8viLh0Yy&Qolx^hrL3c@LrGDE6{oK8vPAqXd@leBgVnnc*r)42Qi$JqqFCDRKj zbAAq#Jx<9?B3Sgc(wH6>JD=V4=*veRdFUC;)xw5Q;v;L~9wU9*lmSm)AP&=~&Yyn@ z;|hR|Y>hP^irXQ4ezcZ=R`zl>IYv+t;d&Z&?xv?wJgOr#2O3tq`)C}*v&`2EuIwa+T{ zuTF1%L{*#b8~Mp4fKy~BX-UzNrAw*kYlvO{9u<^wg0;eSx_6DHtzBZjp+D7uEu$+% z%{s8EZ6)RqIh(jAxF8E4yI3Pojd+D50en|UoQo`IPaL6A(*3c>IF3b9@dVNlNo08< zYU;_r13L*I0Q2agniH_p;+*)AKu&g=&8li0g!K38GOqGP7tWR9@W;Q596W9AnYWEU zM9}czH;**__~)3>w@y5+wYYC{kGZLFD+X`9|466y?YcZE+O+J@9(^uCjI1-pQ4I@C z{r}If&_&AYMqRDNv5M8aHo6$wwO{bAaIEVCCTani2(e?FexbY|LXmDv90<(57e!^I zvB1Oq3!H9!F#n2!1DseGgnq+1=gZS8m*?^2Nyp{Mj>}V23NBBvN3f%dqhq5$e-cCg zg^w^QZFSn}OdXZ8un(HsitW)cv2?8xhwOTk`Mr6`a#DFMxXS60RS2kDRE=8}R#le{ zSv@<2#VLPmDD|~26OW=`!tUDI4Rn_lU)Z1u0yT%>M#9IY? zI4!!T-6EtS5d9De| z_b2>Jz7qE3n>9r#s`c;hPXgDeYuulTN_FvYX{l}u2WYQAQQko*)3+60L#z+}T;ie< z-o(CYwa4sF0GHY^ zb;(!Zdy`0)Tx*TjiMWwKnHI z5d8>7K7~AatLDBWNM$<{Ay4a4P-VxFv)ZKfsd*Qo@fVeey(o$~3=(fGUMYW7ARQC( zHqTGg3&)+2CZKBVISAK z8m7QXV^m#?tqM5!;gNvfDt(M|FZ>9giB){_l%icac-{cY` z-}p2VB3NuZjfw1slC^CT-0ebi&!bVC&*a`Waoo75uw`QvfX8~L`>zG%Hj&)GYl! zjqh-q_Dn_llksJnmc9y6(X2Tmy{)S2=bE=g5&1_y>d=bTT{;Aa+RTvUKjhjrc4|9# zZvhWOYx`RM25ZA#>(c!%{SDY-kCfdD`n-yjz%i`!eI~}@Gj2m4e%D%7^Ea3&>3^@k zA?LQz@l%_OYE)L%@Rs~feo=lAJ&cmu#s-HdA=vE`gM;6ed)r=KUAI`{=Q#2I>TAHb z`<97*z<|qvtMj<5H+>#5E?>dtg%f7)8uDgO18sHr(f^&N!6OKz6f8ZvScTPn4px_5 zuhyxGdwlP}14MU(RGcwq(J#~Iz@9PoIZ$7u&w*%kNIL(c&%w-gh0lQwAu@hbm0CZY zIQzp}Mq1fVqlb?e^^-dH6=TKGo%g@0&h>R4(y={lckK6vaSlC?zWMzP)H~Yme3_@k z$^M3_{{2t>2D5*;R`1B)@NgM-@F%l-jj@tt2ai(k423j0^-*C=Zo1h=_!?M#R`=j* zsOsB)?rXTRL+fgErbbVw52!nZc;*i{L(+-+jv48%^fS<8UdPWsc43vD0cS`QgVT}Z zdp##YVJ<+^z`_#39!>=0ao9}S@#>y=`JI{l3%28|O058E<^evRn@zLIaE=3L~+62yBW|h@SQ(7Xw)|RG!xbR1|=WeLuSBz?KS4V zeRgkFtF-WlR^aLxGrH%@tTOGT`=5XQe&ZKr!fjwOH4Y!3e6VCzVWWyO+DllPI6rY8 zP&*T!k~qUL-g&mC!8Jhj)Gtt-3#{1d;Yn!5Yuaz%MPNKhl)3j%ekdFuqG-?!auwBZ z!jr(Xw(um!k^?}6eWE>|5482Gtz7nI>u^)m3>4X%@Q+^!ezaYWAb z{n!^K)`DDwgiWA2IKp%_NUTNp|0}Eofo<(N@TtkN*_n;8eDy>>G-#F+-J0=5b{F z^vY@VQ7HZ4qklRsPJAv-n#U4dj$Sd|JuH}6Tn zScI7;=iiC3s5TJ)DELZajbWIw^`}uIFaqePTf`1I0t9w5&E5;*+y1}GRUP#&xT@oB zDI=$I4X)~E_m!0FGk&{*tNK}9hq$Y1W9`6Xh#%y>6fJFp$-w*|hXi$CRSv43}SGrBt#c^F&jY_x52-ZsO=5VT0qO9G>z9$ zr;xtOi1gO3-XPaUFXZ1fAxsIQ+i-gbY}BuCVK>M7&noF?BuXB<2e<$NJJ*6;!({4UCR7Z=p4 zS0Laq6Y%v)KSmtow^7!m+f~46p9n%xEKyPcn~9$kn*t`9lrG{_5Jzwn)q*6V(=gy# zC9f_#8eqF3G05CcmH%lPnOhJf9GNQqk3`T|J$cfM-}b{1)~9VidC=CC@66LzouIVP zY170|G1J$0Y~n_-=d|&G@7$kal`$9kq!L~x#^R7ZnQT^`A!R~HT$!rskd^)H`6Ypg zPEstW&B&N7Cm*YnpvMIAQHDq6(J?bX&ynI6`Bt4h|+f zS@!eKR^+XEc(BX9mtNXeECYmHDi(5pP^mnNF{JAWtP^LNdBvRTL;J?x{c8O8C5eF% zM8BQ*ca4PZK8);Qf}Lttj`&B*K)!Xl=CwoXxKGqGKGZvy|lXg^MDg;~=*kbECfPN7HUusD$HIryPaaTdIIDnJFU57Vk zZE2;}W<)Vrsl@9C$bKB#LUFO!ns7safEZbBo-|mn$n~g;d1Joe0LBs5B4WQZ1otTR zPFY$E<3Tj+UxP_0LiS|YgI7RG4;cMwKuRA(VC;@Y2#onbr3J^*sz9Y8IL)_#_14|s zg;@c+C)akDDW43I57~kV86<`T3v?}QUW&Gab24l=_)AOFoDA6SxW9q-i3DI(D#?}d z$z>yu0-dQaevsS8rXXtFc^$3{R!D3LrZ)G4lN5q1DKxF_;JStd1RMYEvZAQ+k4#tB zj9CGSXa?N8K5MpV2YpuVBlE4slPJ*5UW-up#!td@t>LGba9poAnVc|RuL1943Xk*qC6(}rcrW%zF zMWQ&)Dz@@ftG`&h=1npFAT!U1?Z!CzQU)j?vL8X%bDj9ya)R;0^ek{cu<3+5k_u>h zi1&-4SoF!BaPV=!KMRj|F_J;U8K_(1!wb~hOh=G-{H)mj=dJ&EW!Qwr{~8;s$I_jb zIFR`3n9v8q5L9eOfZ0fe90(CGPVRZH%>j3@lmuZ-Bh?6~E7}W@NK6a_zrIP1#>i56 zXQNyRB1a;x9J?$vxZ6OD7JTD^O6k5^h z@(m!3>L4Xo@rXL~a&Jp|RT5OFcCoHOeo@HkK-M4Gqh|k0G@u;8UKX8Cb*v+iIY3>v ztUHS&r0UwqLx7+e^h;h>yBvbY#f9FOR*14Yc)KFCsjB<9c(TmhWgq|L7y6%5Hi}nG z!TVM#bE*lSCP7Ys0^Flbp9uLU!IJ|v7o2(!U^Jx9ux0QFmBeWTTP9c+I37?--AbA! zgg49pvJ(i+j;k_!JRg1e{+L_zHo9#iA2 zmI5%TSQI{!kXm9s$t4$oQzVLILMsn3mTRYsWxoqs+0wfw29_#I*AIu zzJ=Hyo$K6qc$wz&3NoF2QLq_#yjJ-s2M8qV?%|S`O z7#k%$X0ii|#)hFKi$vv)ldl>V)ZdKrFTP$jaaNWntv`GGubVeN{^`4+;&US_;@uA) zfBf#LsxdM2b&YXaWMIn@Ry|-B=8d?hvYJ(6+_1^cVuv2e z`2D0vcMi{XM6R4|09rlSq?~fhHLJqJ6V87<&j-qodg%iQ_qwx95FKUwv17h%|H-^- zgi&)KI>&O#K;9K9c+eX621F&2oH%C^a>~@tm1uTbC>DAaP_WQ5aiGZYCuBhyYQ)u2 zGRrg)%mfezccO$PktIc0S{WoIU;$C9F$5>CI}xXko&{}0t0$b$rC2>-5R)C-pg1@r zJVGuP7$GdHf3-v{Uyv<{|s32{Hb&k)i@} z6N3dr`SB$oNP@)b34w2>NnS}qlcKXJubvznt~n7znMR0OcLV_(s1Q*h9^_yX910GJ zj;Y@O!-5&yE>P7nYS+nY*qDlxx*d_8B&t9h@ATvskcJMXlQ@+&6KyHzi+C&?upJ^d zUb=lPP8WC&35I4uZNX(hL>+XYz`an?h1Pz0Z^4|E+cvDS-*i`z%>GAS+TK(T*xv!6f-lW#x_FB25ugOv(~l@zp|W#6t7L zgYmIA!p& znIj7f>mKN2)#6fvk24tvqgySm4y-%pO-0 z;E87+eDvjvL5)WJvrGP<==4DaH=XTTe?UAT!>&n)XMgJK`Ddb&Qx_EMP0L!4n^wT+ zFp`1E&A>9K50?9Cd?mE1fU+uy%a$^*pDW3bGRPoG)&^X6JOz%wuzYt4s~&eP$N+cH zJd!~Qlf!6<*>$nqq#(Ru(RBUvWRO!dCAAj5hcK8$z;waeBvpAKClyi&ja+1UkLCt3DafSqY7nZ5y^g^CU&6%;|ZA(=ZO;!H>? z=lv0x5)p_piw}XU3!}KFrf0z+U=?Yie}bOyLBl=M((_#|WQgWrUOdp#J9Z z{P9U48LdKq(xRJu-@f9-d+()>*9vP_Q1}A-gXQ4p7@4Esh>viHQCdqe5I#_<4Hu{9 z<9Vihu6}Imi1rhW?tydc$5A^BmkQ(!4Yx1g_w+Nm2Q1Ti;yG{#^jrgi4K~BX$~nkC zYJjyy{E?Z2N0jV1){X;%qy?!oQHUt{2o8KtCa`?iX_@kXBhWrUDl^mQ+;YZgyujiB z;Vw=}Me2jhL9Pz3l$og(OFUt`ReW8&uPk__@#?YT*W5_KRp3gIEA|-!FPDlEqX&kE z@%5`*iTb-GSC0>OM}|SbfW2aTIJ(_wxFuqI8TnKkiR?aWe5uG#EY_TH!Byi+PD!Iu z=~wL(l~=FW7*&8n-zc#QOd}h`HiP1;%xC0i={SvwDc#_O z`pV{Q3hTw)Q2O{1O&=dTdWacf1m50c_w~-BisQ`-O4{*hUEH}{2hi}gHjnN;)xCVp z!K>U&8h=PR>=xnaf${f(G-&)#L5nqZd8v z?DX8!)6&dWy9Yt^`0reU#H@pyUncI#V%yqPm|GCzAeUkLxs6+84Qgb%49k)xkDR}K z!|eP)nXL-u+(7=qFTS36uw8pM`wIszn9)VlpPrF*yK%Bkqh@(6#Ip}8!-NgVO+(p< z_|wyd@qB6X+F4n3nw35;l&61^4#Y={Un_0KkH(&64I4HSH`}*mPnkULu6YFok)_k_ zDS8oeIUe!JI{GwoF2B2KE+d0ds8&|(oO6S~x z6J`wQ(lfR!wrAJDGjHu*yK_>jdbc!x{^I4MH*Y9xwqe*Sm&NG?GrNd-GcvO7FizBN zRM?;;CR6yD{wV76RKB#i*@hPz=jP?*HhytKv&}EbiTvQFrss`Mnl@fP=RMXAJj&$X_^CR3%U>B47qAA=t zK;d`I^R(-TyI7mhbM7_~C0*>c2)GGuz-{A3-kJ?y)-;G93{go}NuAv_!h@Vpchmfm zj`Bgr2v2+bx}E%~T~(%VH|*7}t#R_JId$`!^UbW2(_552;$>gu8BJ-Q+!S9{hhaoxNelypfX=U-qp%k~De5 zf^GNCX)+uh{3RW~FwTl6h1$P(@1ZS9yDFDFvcRfb`DYGZ?aF`hYriXBdHm;J5NTh+ z^OXksVyfMPxK))Y?V2o~C+C$U$?xEJB?87QVs!ybKiyfZ#KcCD)YIrtQF#KA zDLu~}6zSF3o#zR}i9@JxNT29yq6(TuMrFn-fZTyTElPFZpSGa!wIrJ+?l`eZpZCtn ztwH4hZTmR%=>5OVn3Sx?evvKIX2tg%TFF;Igb4mrT%z7-f-12AQe>Twt8W2gY9VTgAk}#ttFF8zbOIkDs3a zi-vO&oH@#^qDgs$NCPdwmd%^??c21a^utQ!CU6l1i@_EbfpPB81>YB9LaHEerLf&> ztOEY5r`bO;jsL6u!8LeQ|E^}wqMQlz?`ENV`{G57z$lC6&MDeZ_RL91mi6tEfH8tB zYx5hvQ{vV%Q3qW^-=@I$*l2G9AD}I&&>oeIuL9NX$mXxis3~1U_M67(8%5?bPkbw~ zdl+Ax5b0fwFAg0%qcmT-UrgA4$9~b-n6!V%K4a?>OZOQs3q&RH-utzO)#-L0JUs1e zZXF!+yh^<~2l;i1%IF}KCf=9;QXC}?x$=-5rC_DPrxU9o$|EShJE|}}7nHm)_X{OM zczj=KyMLZ6P9exipL5vmQaySM?9YZ=+XHO+_$ZX(C`MQsYuj#G4sZqseMEHrD9S+o zV0teu<-owiO3zkihL(9aV}@vW06e)itL;=#xcj+_Ji=kr^4!Qi)s`j zY}0H@1dvb#q#0UDnYS#Uqq$`p$h|2m0IYJ@L0)^4+NPGpwK_N-CUw`QAj1u_aQp!!>9){bg{Tdm-}RWQ$oy&f^Tu zU_$sg<`$uaa4#jdJk2+i$H073=0q*TbL9iXdO;r170;UGmvoWOn&!K^M0f_{*@XO( zLGszSeD|OT&pfP^x%|L$J48=D{^F>_Ou99Cx>8n@l)*!moNN5_gMXB@t3nTeTbN|TvGXN3hM zj>-IYKZ}3U{@?xn%J;Xi&lov!hNettSdgDLaS#18Q&T45rv|qM*k_F5-!;n5&%0G= zX`f#8<3zQ_PfE@A;4iDa=b0LxA%5yPVSF#WUh@`peU<)iHLcfpJgwWJMO~5T|Mt?y zy~mB~jke9}iHvG({ofkl{%^6T0&LxlF^)BeHEOm%^H`DtN)j1tUAJ6i+FleaCF0ve_u-<{Okyag&lh zy33jnBlz_(&TaPQos17hD=6kMD$F>bJ4Ih(*P@7R9bKM^!($ZVxh~45YeE){#yxq9 z@sj;>=FtG?G9p*zvg2Ot)TUQ{g5MVzFKMR<)4^B|{N9FK4f?%0tMZfopTyRYn4uBQ zl<)zFe=uh^;{%||00`hPIsgGBV2eORy(-%Nw;}|v=_#G9T3o&Ub7g1F)QqaDS^FkW z-ZzHfyji{nIHaz^H*M37BHkgfye7*I2TKVvRT3C11EzGrmndE&lu=ExAel8xX?GMG z3@7%v=opF#B1a#^Wo@27II1}^$n2nAmWk+PcK4;XPX6ipM7eO!v}v1+O&xtdbfoiDwQ@FazLM7kQ8vnz zNA+Km#gvh$oRX7N<$odG4Wxfk4J&YJLceo{9C=-w$kV0G7w0Sq)zi|+c83KCnhKjI zl!lT)u?CO`f+s#H(vt?JP`5<~?JQse{yMa$4%(?pPsTOgIO_E;PrrKeIwn6|xOh>I zThpFf^V}L^r2Vs%J$iG}z>mi18`^(( zqb(HFrh*t=q0?C?K>Tt=Z46i}oEs_46$^sCNjXsF>t}b1k-jge2#d^NyxD$R^>>po z_&>b6NL(m0Vzd^bg`rSVqo@Q86xWIgB{ofBgJJXxy&Kzt>b%n}Pr$kFfcE5S@5IDS zX+t_rY38;FMh(c~cENU>)gi$&)DW0yl(!D^Lq$PVMwbBT1XkR~sJP5;zm+Ku?o-CU zV%)sXH%fVsY@|xK136E#T0hJ&{+<1RHAop%DLW~#ld8m*iTC!2myVV1GxCUVNZ2-2 zzOUVfJr{#IyVd5AnSG*pzcF!}^v+TaHW9ZmvkwusS+xsITAUheZM04Unaa)-2?cbj zv9&SF&o|Y$+P)!zpN%z`+JG&l^-vk0QvN{J?2XlW zcq4LSk5C7H%zGktJ*ec2X!7Ys7~36%h=JsYW8{lf&)I=9#Pe8VyWWKAz>06>a}5YC zJfC6=Bpw_*KhDq3i=A9Md5kfLayRk(JM(!?b+9*5)fO;_M6vxD<)l3u z!)7|g`+>Va$X{aROCsdWL(eBZP#egjp`xmwMFlZd+9KUtLB=q2cT2>>vy6q}fbq6* zvcvA7fDLU%`syU#kcvN*+s>c&5sw#PGw;IOMiWBD-&ag8`ueZBLiUW+l|Yn-GpSf4 z&Iz4~N(W_;%FYSry3!6iqTT_F>lpCNZ+()uql4DM=>6Jj!tFDBuZt(VUdpBvl}8~r zC+`K+#iY}d_-Tn!965a@fgms^KwU7OpZK==`HAfjeFefUnlu9=?4sHFk0vF-Y#V`* zkX#tdXS%f1fY%YzlFOo6YV&c~@#7=Jry^PPomP4oCyng6W!i#$YuD~GPAU`azWzR; z%<-+(5D*ZRUdXW#aQD%+i6)y{B>E0HmIOM(x#MtE*-+lrLI_ra*s+|Wxc?w_lL)~` z?sOy}1f!TRjmR(M%m)&W%T@ihy4~}g(zoC42ZE?%<8HANM8SuLmTJ%KD=yyWJ0l)2 z!hBDQPmNsdIm|s!;ri>4cQ|1$Id3P_j|h@^MO>bn)+pnnOj0gznS?QyNf>nrs}qZn zKnMZN8L=cO1)3ngshTi*D!*SPO7NH5S6z-jk*-0$qWvqZ$1oc*bvSo71bw3QXh-cf zGCjic+@VZ$gze!)0dY)oD0L))I$}dAZ?UR5f^cG!fy}+IMAJ$+QZu2qRGo9o=#6D) zru3?Fcwf_gKfwFFzNt5WL&kn5{P7dK-!I7Ls?5{d3j71=cp@f(N|P7^vrm}(QA9;p z5~6Y?EO=A+Oamr_$jz|3K?DPe8UoKD9s+PL4JH6{Zk}een?MM|XGpqpYnie}9q(IP z=9`VJyi{3=nrX@u-$tpUA-D06Tg^Vmef&4}fl%zoQFz#&n+vW2GdUM^x+*_%ltT_K z%5h>jVE?jNf&xfL2jb&QHF-!O1hbZk1p|^OGoovzTxGH(!{~w=gu+dTanNz*;2KVB zxLk3VQPMDqd>y|e3XVJ{sYj1<#V_ASmEW#1F62F#v;Nk*HW2lwY2#D|>z_kjF4Q2e z>MP{s`Fr}xyWn~~MauD>YRB3h&ObJm)HvCkoQ;gRRXB#@DI_^jlSD{;)xiat7Onm zq<^CqZP>UtEHP~0i2ci#Jz@Ov-VerUWmv}+sNUExBP&n*miLQjp(#i0FK=tK)~jfB z9v+``$Np#6X1s@r6SY3*@()EM^{kiGyk{3O_t|C{svRSng}BpTeviLo%jO~;U4jboJ`CNR#&l7Nd{ekv6)vm{T&00*r zk;u5c`Fordea(or5_YaQObHHP%^b=WJ7WrPSo3KC<}2I}y+LfE2hl+m97Osp81+6F zV;e-wM+!R)$yflTawdcJniM2}^?n5YA8t&X{F@ zbl2kyB```ypckm^8A>_kSTnM86g;ZXHD(5Z37_BACuUnt4n?jj=nuSMcItK*!1wYx!K*B(ZV?8Faiwx3`)-V@% zejDastJV_Fe>dmmM%F#p0VW5Zi>$lrvhYc#h{<$xEd!P9c(UQ`E=@Z zusKQ5M8jF))}4g+6p@JVNX>gSOP|0jT*1^QDt2Fktj{P^KKEr~58Q@(uFU7J>ie}a z`u~=`2mOn_=TP5kX8nuVd#;iAkBr9=zK3Y-Q_SZzUi;ua#Lqa#q&-ohhqEmKy>D?J zR$;uW(Fn7LoZ-ScF+kCtrFBdYA`=6RGt1$eQU=n)3K3qmeB*$_y`gJfjB$PS3o66C zb>D4q(Y}GSHWu21>eE_9gp1#`=~}BJ0(6{%m8VUSCTs6>%#0yJ?5mf^W43}H}-umcc?mo=SDX@J*xL!F%76zuen!whQ$ zKs#{75o2mJiuOgi6Up!7vElT_HXzDj39$qh))TI;xfFUk@qZ|r?~=Mk-medz3H5iN!Y<38i~ zGW}!YkJ@R^r#2T$MZ4JdTi8=Q9|AU|RKAU~c_`wBNx=TzY1UkzTpLcL2Jc5nN{EXx z!BYqU&gB_QIVBNgyl=ClCpOCK+f4Grd;U?y{jqmR}J0`|8w9_Z|A|E8iGJTef`6 zy={86IkEh_@w+;2ktkEdqoXE{n5mArVMM}20pP|alFkrA6xJn`ZyS9{CU}0Ud@j1MjyZsZy^GJ;2K;jb?qH|bZ_d68 z_|0Ep4p{IC>4N>`?7P780nBZ*sdBjX74}4|#fNDT)q;4EFBvMuDv_;@GmjYhU{r&o z50^BH{mbJ-{J7Ze2n~ZkK?O~Abr96OTa~2=`3BEO`YLY`yvdu&W{IP4C&YhheER-? zHFt=8TZ{|jQGh?;c9(H_z429}Cu(n>v2C*t?hp7CjPn|<`RJ#~hs=%-b}IbmowK8J z#cEJgG~ec~)iWduSu9Pf_r3h`vjb*L5*wF2N&W@lHgaoy>0NI8-rzv?idz=m9>APU zn6n0mRh(x1{|3zsVibr$;CU>?DA+c_vi8R&gl((Q-5$vI8q5C`#6@$+*Gi`^@@HZt z(-9YXm8z63HxNE_KTZP5BC{?v(O9}3B3;65)na6&q0s@x73Xs$K9sni=*n029HqmD zMYf7*+1|SOU3QvD@FV&wPv8bf+$G($K)%mh-A7VK|L6M1iOtVFlGReC?BC#LZCc^) zqxj9}4*71guuyohwNd(a5%- z1IS7!GOye!mSl21=h6ajBP*B&f&dLlz^mv)2nM=fvVKv04~Grq?!lK*2yiUUO9GP7 z853d4PBUwkf^KAx`h%)}_x-dzy&5%nYa_C}<`_GSa^nOFX&ruN`^%AvFI-u-O#es( z(;3pjm}VTVV;nWc3o-t@_k$mvwqr<;-8}H;IkjF9;kItt7_G$-foD8U{WIv&+?#MuU_6g(p z7BLggna|JuCZ3Z|81GNRO$hsK49>jH&mwyS{c%5^(%3JP~JD`Ux; z&K$^?1aAOWv>`rE$|UtDq=qAq!wfd@;;``O1Ul_pk)B9YHN$BKgof8fMk0!;(urrD z_Bi1=*Qp7L&@@S>T9C3<#~Ahe$|;NQy>H7paf{-+PhBO9B`3Z#zWMew(8NkM^bITb zi?#Mwb{L&pKfFRT=rkr{wnp5QNraJi(#0D6cPHdsF|_|fBWf#fZ2#L4trvq8-^1!! zVXS=pGdUucK63f8TQ;nq0Ug_6bcjFu@@wBwji@c~i8=H?Fn6!=x|wA=BRblw# zO>3r!T$6sjbOo9NpU3TJ|10U$-WPy%j^Fb-e^m^&+S$+IIoi?t(hIpga~C@@(XY?V z_Upwgv}dj%`g~C?+lR}~XMS~-2SQJH|18^fmIw1KkUWUP4ey`jlJbzXF-RV={bbuh zmWON)d6?}dUy|~W?Ymp;#V{lXkUm6vE#Cf{+1`N~KezLq<9ij$o9|)Rb5h=XXW>0c z_b`k%L%x3#&I80%@c!x4fAyRVu~=%q2H_QZv1}wKWq^>>Z&K(;!`gO^oHNx z+32o5rnSKD&y42ZAH0WtZ~MdieLn1l!F(RUCZyk}Z}Q)zg3+@Y68gbFd zzMyXutm5+OvM;vl^#ywDT75~B{vDAXjBo01Txt9uqL06hH085P*N6tjkMF%FKHdkK z&AY`cqsu;{Hke_Tp&trmS7=Ki6O$*LsxyG6SylxoQJnz@qe+ITD()^xVs4pS$eqQ- ziI{1*ZXrsVlcANK!6z4->lu1~5rqtzQs1W+jUUTaucTy}m8-?c6Xi-0@{w)t%-E@f zZ?g8Q$~-wYa^J>beeFiys5T^OhEwG&50&dgJdeEpC2DG{zk8AZi>eZ$Bq7)x%9=~;?qRJ`E3`|5F(M+z~2a*s!Pj@i=XHOyIdO0d_sXI zhim%E43CDC%F>VyIt`I{;cm?5TP8+;+?9G58W=7K83Ly>VlvDi-vs~G12WC4r6DbW zd9sqJcA+PVim;(tI8|NENyCVf!P?jm4INR)%x1GAg7^Ylm@_@Lplax-ETfw!_Cm`s z-Na;X9De$ZzRU8tDmDMnrr zflC+MIZL!{GT}BUn+%~D7hl_560msU2RnAGymPH~;rNGd&D`54dw)^KR^6pQ?kXNi z0#SE8dBdbTk58XFekNp)SNWahgN~?2_5#)p<`}C#G0zhQKWrvS>=NNRMxXK#12}5Y z2sI298aK?+6l1Q8bVfQM z;qr=sgU=I7g9mOB24<$`iIDfd8#3sYp(3O1;8B`LOZhP)OR<-Ec0CZ#ug5v%@GT=o zjx{c8E%t5eJtHe&-k>&h8i@5vd+g~oZbO%k&#E);=-#sZ3!U3{>Vt9KXndy$%zZj? z!oes;k!tpQd(tuUaq$5AVQ@6_$p1!I7ltG(IS$yd)(f-wUjMp*l*~WY7Ma(yi`#uxjmK6eo6-|Bhv6G*N$8L_%o5|7a z%p43HIwC6=B^2b~A(Y@OQYAEaZx+iZ3-Y<19I{9b!BH%SIJm{=&Js_j9>D*WJj^s) ziq=$-;EzP;TGeJ(gD)YS`_c>JtsG9`G^5I z!=jwgqZ{_SX<%`;j-3XT4>qMiI-mo1p%(EvKvXV{bO5nR;ul=v%Fph=+>NNtlS0nz z6uuykM;qy+1eZtP*Bww*rIr}v0*E~Z4y`aJJboBpOe9sS#i@b402+48dI3hm<>{`m zp$|!4?q1zpi%k!=l>KheJ)P;>SKs|H{Sg6$ax0`{$X6g2$fJ&;XG=* zOLMptb9g7_FxiIj(bUP3v7oH>`*zeMm&p-l@mHW2FZp(oCHvdR&rxz=???H?1|m2pKT_cLS62 z20+H#GT|;$`gXqg7MijP890B+pFWH!>kY462l0YAVZ&Y?RkUw_oUndIXPT?gxN{$Z zzat&Ij*>$aBy2JYj*VxP{WLkxVfO)W%{4L;^U0*5vIj3OEbU8W4>Wfy>K?=$(L9M! zsCy891c^w+uDIB!x-id*6XFw5`T+l}Dt+L^FR}G(hvMR6T?vU)0D)@E#l^c4=sS12 z1R)99f{FQ&`6vP$baf9Vun~$*Xwth%;dGo^)v4L4Y#NwzX|~a#rwE?m?bx=%Jp=X} zJ-TPnN=+ojUC55XG5zI-DCpwl@Og+BUca6@J@ca1`0LO`v2tD?&&Wro_4xceD#DVi z27vSOJNV?&30KH`vn(sp)Yp_135rY95X~I2P~%d`0|B1707pCqBnRRRh@&6;gOS-i z)$7g)IX%))3ZP(Ih^P=>0b%WlL&Zj%OQx0Ggy1&U+L9UCQll9* zB-xZ?K9Ehx3KjO!@rp%KkyhV~>N1R>Bi8Jj*oRk)f#$&qeg1zj25A#HJA&Ni0I5rJ z@8O0}arp2XK_GX2#rG?Qux$2?4|E%~wj)d)=*b9q2CTpsE@R)-L6sJ7Et-ck%tIR2 z4NQX>D_I1nR-2RK(oRJ9OI!)H0$~S%G}NjaNLo`Tdyk-v(4B ziVc;uV)e4wccL1c{ph%QuVK+`b=JmlVcuK+VDLe6#Idn*;ufZMa_!qx#6E zKYO0CRt&@QrFcGDci?$n_E*eP91RAqW4xoaPCVW;-1RRxUc-BGSPmn#Z$wvWkM*bM%kf;wXQZ}7z8~Xi@A%bf zug3Jbb|KN6mQoes!MhA@YA!PUrVO>~BA>wZ{FF{rS`1 zelGlF_00F*tJ8R?Ke{@%DdHA*&g}zI{O#x1c8Dy0|G)6JpHujaY)|rWbTQlKivH-& z5X^rKIZ+IdKPN}@Z|&mWLRwXy=b-npywuliuZx@fpSQ#Rd9RNRu4*69+24L4YTe## zwRdR#_6w(WuhxFPzx`R;TcW?eeWAbo+3}Ip+Ji&G?9UIjcZgfVoIjc;DX$+UMa%X) zekryY+tUgoDxcdA=hi`%g*9GYkFxz7+e~Xc;{B)n?dQ~$`iyg^idYosj$7*ubb@T7A z9vj86)Cqw~pNDvw;$rzCwvFG6REt=?@bikx`V9OX<7)7HRAnjJKWH2j5@##hk5(7+ z{M~`)_rTAVLkMO11a%}op9ox$lQD3O<#T&9e;I{qC$!`pbT5J6NAk`&j|B-?%;I?+r0t&bM}n^$E3yKIz5!1b=hE?sQ!8x1VSG zC+X+Pwa_Pxb?qGgS>*In(@euAm z*2fNBA9vyTMfT6L-yiLx`1wNUCGbq+{XjO z?*t}7yZ`;rXR0&! zEa$IzpGWvA)e4qBwWsylqH-w4E8kE0Tei3C1AaftU$!5q4QKhw_N2dM`=PeoJYLzJ z_93;$cvE=1mHD)v_3e00`^TYa#;djuVZ%S51S&r&Cy`~CLAm>&PCQ3n0!hCf8(@BF zJk>Dw*x|N^Wr_>L14>UN@YpfB!~9?QTgd7WWs3H#+9;y4I_gtfzk+tOe)lU=?B=tB zwsGUG`%E)#P;piwA_fM4N`VMmM?qt`N4-Z(!F^0a9u!wLFF~3HMlL`yKzJh!3=sGN z6)U0KC__le^8irGQi&>X-ZO5lde4`lz3(eJFobOv-bZ;88qPDm)?M*F74O5B$q8w_ z$q8@ft}n)^_b6%K8OQ%0*4_iIs$=ULp0dw5G!;Yv!GcOrRC*OuirB@54J#@Nihu}; zh>Edcud#O%V~mM_#3aTf#u#Hvt}$wi>AmPpF=~oN4&Q&x-sgz9$$g&p{a*cTX74$B zPg%2O&6+iP?j86@Js8!M(rQk9eLZ2V{db0JNaKCH)R^fS9w4*uB z`FhIE{6)r2@kBHa@G37=~LNhqL8U7OXx?K++Q06sY1Xeyxv)KqS|I{Ce;ldlWs z53Co|9~6x~CSq{IzPGH=WBC;EtFv6K$bz|iLy|IQT z7OpgpNvetSI9z(8^oEV*5JmDr)i~9_)1u}KweU=Bztf~tjW$*AI?-MJ0oxZq-8rO2 zQ{!(WhQ&>dLo@OeY$S$#4czjPlLSbL&G3m-QIa)zPRZn~IpRwHv2#ks^&ek6ON}?? zg6zSr!`GWT(FNvCSOPpCe)5JrKTyx7-{m-rnVI#4Y;ipH&AKnRICy;-%HC$xF$Bf1 zh^j8|5ztrnE>`6Q$AjJdVqnEl85B{~9ls0?uW@sxj4C(sL^zCQSWQD+ZL*pLA$d@1g+zqQ0x1 zJhZZ3v422e?=^>>?30lMlxFWJcsIdR`(Q z6MNM&_FureT((6-$m1C4){IwL)CifHF-H(S35zZOn-myvETJYF{71XD&E>vN{QmnB zqJ=wOYAvwNQ01hf9G{2Ffq1z_FX}-#oXUxDhj~R)o{mCrj{o@5^%{gL~s570wjO)Sllaxku zs-&OtBkZwlg@NyArSJ_$G~^}Q-7wt8u^D-ZCbe&f+|@y;VVLisJHJ+n-#J@-{qlR2 zEqgtsTSRJOu}b>RN$k0Km(|4I%o-UIRC@_c0bIfDQ+#Rg1=#0--Y>74W6i_(4?zAj zz^xs7){wD6E(TYQdV5Jrp`kLxZwND!8vlS+J<(%bCm&~Wn}K&7*rF^ zLgZEG=OUtnqK=XznEv6%5+&joz(ql&2T97v{XSI5;X;}8dz*zoVcnO1#SN2RH=>izoJ(#J5kBz4PM-)#jY6 zMYGDDC_mV5Vc6-@E?YAWmIIKIZ390{YZ&Qrbbxl2el8KH1d7lp5Tv%~4*f;)^;_92 zqN)kt0{4qel__sioC?APMIZ%UcO*l%j*91ik(c3uf($N9I@ly8++V4WI#5EA=ddo#Jab4XOskwl4M1BrD z>%eMRwGJ-e7J{oP!ym|9D_z5D7!Rb_#{e6{r1b&$&{T$JM3o5{O~a2h41}SNf?JTW zHUm0UO}wx+KY$N_RvpxW5GshUPgAE{bgl)s;RK~J00$in8w9@zM;Hx*-=s5@+w#?+ zbf#j0li*6%Q?O~RbUt)U_%WPwn&-yczzzDimi?+<{%zjve?v`18shGP~l-`4nzX8S{P-7sb};*JHld-6c}&@$}#(BeL0 z$C4%6G_kL1T<0!b<72w+6WZ3r%XVCzhsEUI2iL86{PA^b4nEl{C8c-w9?5;N0+&C% zWvV$eH6y8i;>grs^VCP5x__e=tvNT#k36*yi!WASebr4Fo&hw+I+R*>Q?3K7eV|`3 z+c@!Y$04%=5e6960LPm`?+nK^nEuc&@VW~8Bqe5|xvuK`#}!nt+DnB-SLZ)~FIm;N zfd6lg)EA(m(>R!oGzHG7kkgHDqy_B~6-Jhz1gja{&mtfsEOeI8)M5@G*VP=1jEzZ2 zjh+~CY-h!h%g4tTnZNihbQ1Jx`wb3i-LVtj|Dv-quYT>5nk_+(T3^gcUA*{RDSx_R zadJXrp@id^9TQTjNdKElJ>vliL(g?Mhv52W0a0VXo*p zVz<<^_Efj6i7nKLAgPx?sRpLxWMx1n(TJx|(^5wu=o$Fosfmt2ME;zK>Irp>2b=wt zu-&inMj&DW0@?rKsJf~-;z_{O7|yVj>0?#9*0^(WG>)x#49Fn`iPjy6+E_c<`s&U{ zZBW{FTP!i(zFj-ltTjBjd-qExckOw}Po!D9j2Jq2#KlrCe_ofh z#hYGyaZ~Z5FT7BD{LC5g+0ZFdh87RW&K{!hW0KsYO~CqLfz>wr=qumVyaD3AJ1B;~ z+SJG$p4(KuEsNf%fg?Qf{z+zru+1=EHI|8LlUkkCk)c@~87hB&SUkYG+5Ei0egnKr zO(V6iD5G>TJ+j$vkRLZ^m&Q$v2}bd?;1b(Sxs}8n97;-y+a$hhMKSNae6@MaqCE4$ zE=$d(LF2|*Q~8V56w%zek{8#04ZO0RhV8WVIn0C2IA>a~d}Oy|(^$1T=uM4_?&nTo zX{_;4_cb04?(mmWYrwRC|pIhh$6;bk0X z;3?8frH7lL90_lv3^r4GkTAn$3XxlaDUPURGf#Q*9qwDpVpjJbcVf60esbK0)(g;* zj9%HN&+5*i#g}}5_561s*5{+*61rx`#Pi;~BX1emB`FTWhjngZ-LK}6rfSzf&4sy$ zrC90uamA@>QuZYhfOm57&P~%PyyM6;u}Qu23UOU{=S$2<$ad`(C3j-{?vtWobk zf=Taa*psSq#-f}#>Kzm6(%*?T%9%#*0M5|g(b7ym!e>Wo*3Yo6rT8nYLaHQ@7+q(R zobJE{C+X^tkt`|b_%wyfK521oOl~His!6BHx~irbhyEZUDu}lyPACIoG+0U~D{StV-EBBy z?WUf?bQS(rB~cZ~G8{PwL2C=PDa1=AiovzdXg%-ONq*moQH=j{!7Oo3oZb4Gsdn?o z+RZSaL|=A`>GBI11}@Q)BqtBa*y;(^WQv#$!5Z{0K|oic@6M3n>Ap)Sax2=2AUaql zoXFk~2kc5BV!2vHk`{0=#IGb=|6vsID-8jVO7kfbw67{1Pf2+H4CYm4N2SaGl>lN9 zm4aPVYj-%lhuU;o8P6v!Zf^GGqb^xJU%n=iUboJgKVOSPw3H;`Zy~R?e4zZN1|rf2 zX09jg^xYy5gXel>2ki8TuZ5X9v_dP%!(_CYu|_Z)nx^eAdE2=v4N&-oSFtL56$vH< zqINhq2X<8kgZe;!2wI^nFn=vjhE!|2iugxHkC?!OZ$>yjg>{W%q7>FOH7To5gF0I# zafgrhTuQH@?O@eYgF2&d2+W{qw}u4&$wL&u{O%<;8pB$S01q zuQ+7xg!Q}|Q-R+}K2#0#f_@y_G(&$~siHK8R~%)mNP5u>3b7!n7KcV2m|LX&NLxo~ zGl^3y%meKi65FITa_j8TIr+7te!V(2^XT9+ApOKazs}atub3RhrE9+*JMHZBg2_BK z{ZB{OqoH!ave;d%4V-5*gO2lLhR6q1h{l2~?J-B`0n2h%JTwc36NxG)wjrqFv9>Kj zksXAG2#i`}NEOtXnPS7p1l18{rxg1a*l&)j3Jn6@1S?}yZxW`opg3?CAdF13hi6OL zQs{Iw0Jf+WvOfODU$R2Vl2X&g3>cW4SQhFOT9%kRaKMJ(mjng4{qPQ zf9l!P{>|G5H|J^HMbY16(wtk*4$7ak@30#Spg9M>lvNy^Y!FV~Ea6fBp2xtM(x%%G z(2)%o1a$767Ptkl&>RnpSYO2Z)v0Pdt3NWe5c;;Woq2~ zFv;#>&YR#_0K&EiM@&hYo9+}0&5xH~;)|^1mzRCwW_Ex7@@}ti@*3(T-q3zH^-o-?{v%&EGG% z&wb$X)-whQww6I%j?ORtW6jo|sCWUJ0H%2Y_dS9ArMhiEr5E@*Qv7ji2G8USn_D<4 zhkdx2EOs#oJe1&;mK#@WdOc_l*3=#BtcQvY>OtEvtV86c5P^_ru2gwp9jaO;S>#yP8}AK2jHrN8Q=_Yat_w7YDg)3 z{)V|$atKf=R{{8N3%?SMD?_U0t;JY4<8fX1v2Jn;&?r8W}+`wr|(F%k!t7+VTH9|uwFnP9wR61Tg#+(|$ zFL`*4S@Ds_go`W4TR2IhA!(rSb?`Eck*x{P1sDkUgg`}bEnF4d?0RMA@XBb{%9dz5 z33922!6C%m(_OS{6$HGM1H!BNeTS6Y`mHq zUYYG$H5;!M=|2~_R+aM($Cj^LyOEld4k=obw6 zaCK0dFmRPsX{5WK&rH``WWIgM>eiZiL1)a!CUz=N|A$r^N;IGrfAz#k8on!TRgl!bq6(a1KZ)Q%WPny zstf>Z*)l3#Sx1`N210dOc}TVY1Z6+Sc`zx|DL_W2O z-xLxN6+VAVm$-z^ziKfR$ z@1Lht*8K)gir|2D9e&>88`!Sh{ipTJ3H=9+9>7bjOFKq)3a(8$Z+#t~Tfchp-p_aM z^4WTIn3pCty7oQG`wkN@FI%!USQ~i`iM2z})SQ_%C5zy*W1BdN~dqh-Q zWw`)?HCmpOuiQ_vUY4hMe23`xh@b)S=e^tY8vEqNiYHz;e|{d+$uzM@zH>k9ewbEl zj)?3Q72dyjOvZ?)F5ZEQ(#p3ya{tT2mOxGWb*_dkf|d=p#%s;AU5x|e9YvGMc%Qm^ z$e&;LlQx%hTqLacaQ2+emVlNEHc9(VPB-6!C+Oy&N|^mMja1K%HERT(!PuTD%UH*& z6rOj)4Lj(RE#B@M?(yzOhet+;rs`r_=7$?ca1_;eaKDk*Y7K=UB&$2)h-J9h9s zsd?RF+xYgFmKxm}eMTQ9YF}%k%x|F&Uc~pvkQxVl9I*~LfN1Ftjv+Np#-Jkjvd7h$ z21;^p%&h@+)Np0pIHU%e%+xK4#q5D$tukR9V!9C`+~PXADHnybJQMfa);~tgI!K!J zsX0+xI(F=`uzvp;KW^R#9yd|SfDNCZx^ z3(dQMlP<)qfI+d~Y*j`7K1mK)&5u5+U^5l4IgIihP`+=yNC5Q;H=~n|E{ff@mFf>~+f%v!Syk%Z zZ^TRMZoaGCFv>m3ovptT+?!+FJff|J+`<{$fG*>a5pc&(`pmRLF%D!^gxA2<7I!$# zY|h{Q1M)TqGica}9z7q`ijY z&U(IPNTT7SOMoD6eAwK)L1X1$17l}G4;f5qz^{@s8A3TI(Gru5XV13z;z+*%X?>p& zrf0Wpe>POy-u#N`u(@-eKAp{Tw{Pc*&6lZd&=b&d_!6@VC<$T)=sXmTURC@7#0)Uu zRG%0q6LBiK`>!Z~vFWfN(nBK3i@?7E+|4%#lr_u!$yha|`35&VHXm`0y=MGr*CHY1Y< zQ9!_iS9w8E8g`XrctP@Cybp;TI->&dT3{t)-vrtYbLt6rHK^iebC35wtu=`o#l;0H zR~8f%-w>uc_Tl?jjQ(}|5_i6E+B`jbU+JB){W35w5s0538hfAIS2g8Y8OjL)FL5#_aq{T{sN= zySj{ubPW#lR#np4ZH??#dr-*QTB_vAX=@uB9*hGX_>w)2@?Ho$ASY4HfX9D>13F4S zj00f%t378YpWX6j{zdHVlmEsU$-i!2=1%7hnKMQKIp*za<$0yb z8r5SeceIa{R%#n7vd)IDW8$kNa9S$m6G;vzDHei0Vl*#dI|XqyXcEcq$uAB>GYVmd z@6!Fut+^%4cka~Q1A;W*xBr~UuUXp}W5vr+p9ED^^nkRmXmsFqO;w>f3V?4}B;=cog1Rra|KbgGOfvi0a9%GcRNabsFW z+T>e5zVOx$e3W@)#r=l(ZUm!TqJv{xI0x?QlV(f!#1KF)v-&NZYmca&&>@(Z9Moxo-GELr z)o7?WLbcf=!2qA6o{KReqHG(4rfY8TyV~me5w`gOeZSRMYfzrDz-I^^u6*_Z@P@q= zsXNe6l4Y+09lHw?kWo}dX-*~N~ zxW{WP=))GVOa>@}QxHT|yj zOWyMCzM5nE`7?Wt9os|vcHK`7%e7t5rBnR2yrUH;KD-ZTFSL%qZ~qB?+suci_&mrr zeP-la_;7ZYwMRMn`_M&J?~{&lJEe;Z%`7c}{Pf6sR1VAa@>b=jd^2nt^n9M4;Gy!N z;c0qb<^Q4c`P_qf5dROqZF9BNcwguLNAfK7KJ5!0F+17wN3k2MIlZs;3$TSS-XFoe z8Tk#;^Wn3}$R7rq#c8&D)3dgGSk9L#U0(ft*c2G=XRu|g1Kx+gN?tcRBOk0J!6#1d zSAw+}{J2s(Dc>Te@s`$Ycpq@qnweW5pWux5N9gkW^tzwrdCZAc4$yTXw&gfAZ@56 zSu?8bb(?^6aec<9DOr<84bN!uUQh9+)un}hZs+3{KK|-uD~~WYN=?rlJ8F7JU<2{! zS?g^NUm@RmuKLnrm|FIJc-Z@qo&@r5&xdV*v2QEkT^RX-B3>~;!RZ^l-w8UL)>xZq z2?|b>PjG6j;H1A#`#hBoJZjCnP!7%M9CI_|ucY_ktL9xb4r;EOgY5akpwmt|S1R9h z#>j{7oGDFIJE{C7sy!=IIYV)}>rL%MdqA7;zRE{?R@mFKMD06OKH9TFwTE~U&~m&F zAu8H4oTt==>-|OkT3bHKnG3xnRet^Vqf$_;WzYgiMI~sAFFco{E@$?ajbg_ zL@8Cllk(wHt!^OvS=ZI=LH;b$F{2##BC7LZ(#S6```Yq(MqMj4?+KozYQ8Sg+ru7F z^EKPrKm%We_aC8rz+r}!Y?_Gg9%uT=mJhhavshccxxGDq7^2nBvFA52^36OwFTggA z@`4&i^ql5Xe;Zy6CLR^0s|~2Q&3ce?NV!-Y>lz znqTUD;9G`jXLHcM%c@_cdcOqLImHSZ z@?#Y~D>`R-8~H?EL8miOGS;nm+S}p}^E$Pk?aQ!_rHFVC-Bz2Fr)Cp$YZMcy2gjh0 zJ@BAPJckoB|7c4~Jle4au5RQjveL;-_ncObVKX+e{@BP`=80#MdZZ*D7v{>1n~!of z^O$%HJK2!V@xkWId1cF9HJzkB>ogg5EILg_9~P=Ptmix0^HbS*=7aZjTJRC_iFTlG zy*en^>9ixvmd`WtI@il@YR^y44Xl^%Y2*{^veg{W%OTpQXcO!!s_e9HiJCJyt;t~P z=>57~0BoUJ6V=>fxz@YX{<`OpKT^#leNLv=wNP^jxGS<14N`NMm3ZM41Mfe9IbTlp zKWfgyuA^>(T61+=r!`l{-Q33Bs{JZom9OJ^dbGag>iL8dlu!K%x6`-_s(ihi)Va-6 zIoZ~(w0Fk)I*yj{33atLoHN%UpK#8iIrB#F4Pe93C|f=s!JWVl*>IHFN$+D^2I=k8 zahhn2%I6ug+pBu@eBv4O{PbeI{dzvNpYo~wGgSNae1eajpUO@s_$1KUt>%(iyXEpu zpDK9X04>9w8t>EGCVkQ&b+ZBIzs<+o$gW$UZ33U^j&rj?@XSZ6H|(la_@v5~N`7Ed zRv^=Agp47f95I`utl$mZ#_EP{@Qh2&1##9v3%VyMaXTAcz7?wnaRFk_T9kVBU)a!W zu%Te+Vj{Ng+Y?oi2wwEoI-M6?Yw)7KUA~>MtIO6$c6)j~#E|Op1FXNy8)tfmC`N6k z9b&VPDj)D4a1x}X2!4turIT=<@JespWoj#%!zA5b2-Lh(Ky(+hT#0d-(GA2nK1z(! z_CLfpB>$-A|K));=Nf+D-Jd6AP9Nvo@Scl#!q}T1PnkSrG8V5B`^PM4-*WBLiS5TV zacwd=B6Da4G;|gW>)&sz!i%}uqvBW6|AzgWPO~nHpDg~MS-xzClBYWBBGhIfHQxH2 zE99hxFjej7>uK<-jezU*V_r>KK&}d}LF5n_UmA*lO`x1Whc`AQ{}4JmqF|%6-){!J zi)vRlIM2cfGsYCMbx4r0TdcOIAh(s?G? zHykmG>ZFv^q^hfyy-%fg;YS>Lb}^aynGTODDH&((6c^WtdyE^aKodW(0~i1Z-4I$H z^LBF3fkbk30bN?nWydMwdd5D|zEuzwh~UnhgU#bhOV9Vo?-}mbqVKex z5q{XKj<#;+1K2spBw&98sk+T73W5pfa|_Hvx^%$=G~e5fzJ2?g(k;igUeSEx=L$bM7;eM#tHg7a72rGplJ;>hAsyAb5pCVrZoIr zRo&!;8+&=|Q0>YWhR9=JL$^53_@vvqn#Ea@WyBEd2Jet|1+Uv(_rCZMJYyrwc%{cf zs@f>gMS1D4l^CUTtOdD}CC!uxyiL7uDB{KQ^@EV1jerw&i-L6RO*kR0)<8vcb#X3S zeNVv(k7_}9TTRJ6u zS9gfsNW7!uaY{+55oy`s&|e8^Rj5@Ao<%80MRD7iSJSqGOtn|9+}`uJ^>-m=+|S@| z77fbHnO^j7tGWy-{oL&Xrmk2sO^1!{i^J;#U~gA#QvNwi zn1I#INq?&e@|rX!z%(IM`UWoTnnOpb0SPKP)DwJFdXmtb#LW;+dLl9SEPoJZH~Og+ z5Q98*c##&VcU+Yl^dXO#T$+==j;dDJGpaC&F6u0S{C2>9a2usl+6P7G33+9YpcwLye%h|8EWyZw9IS;wBEiFDZD`(vN z;t}SfA6+{)>G9AGPnRjLwnU?PVVsMgH{t}W9HC3FbaO)|X9sw8LckIw(k37Mz*NJ! zMTz15!McU!#XnfL0L`Ey;}&S?C8pnd9WjVD+~o7kp8Q4m>;3pM)(?2#8Bxlk6;98A ztOoW)*psh#uqW45e%%q~%+t9Asr-5xJ97wagu8t>j7>Tzv~}C?$97U^t8|4=qeiDp zRqj6UY1HHtgEL9esc+=!j?{2cMAWjXA+&q3L{vT4+~d@&A?@w|`>r1DpZ(^DZ`Ku* zEm~GKeX7^Rbm?FFM91*?Y481X?~iw^U-43Nlk5fCD;91~?BXgTE?Jkh?#M;m*PmE_ ze}`~Yurl;{ikfqQH0zYtw3fh3C7;6dt7+`#MGEwdX+}fG8@-0u8y16=J}NjoMMPJs z+^yjx4R&mey@=m$>Q<$@Tk<2>HzFi7MwDIX77(Xk_g17tS~k~9EimcS!E-(NmM+IA z<0(H5e=IR1dCs5}$Kv*kd+!J9oi9JOes+7y%sG$Dt;k&5g8#|)-R9A)eO~ctac<|r zZashh^b?q%w)$n;v%429UDUH1XbW~(@&?A%g>>IYW~wkwS4o7R7h)C&OKs>yu}%!* zDWX~GER%c^=}~5&)!@Y4U^eB-Vglru_g}irUDjzozV;fTDrH&sefJ$7CR%Jnol5ot zJ~0p)GrE<6q67Xk=ZOvw*F|1>nknm|W=)B(0mKOF2Io(ej3ze;zj16$8>=?RQwB%m zo{^O2o0AmWh3Hrff|lFEb_Ywd z!H4tfd{u67N&dPo{`K3tSAW3?#Pq4TIaBt&|Bm(kN7t-B^O5E;>1o}%4DgNEv2)`K zuRdWOIHrG>#6E4q_iWiwa{_%fcx;@lLIR6}V{n&Pb)m>cbj^XZy>;(Uf2Zngi`!1x zs+hM4@@ebd+w$#KU%ekG-$vPLp9kL64VE7&#t`YilHXn9yn)Pk5laXm zvmyY1jt6wL65QbU&2K(f=6P#xS-<<{8|$}xi}}{iTd|yuaEB?zz0`bFa{htTExH5 zSs;ZOf|jH0sF#Z70Jb|E5IS*39Fb4Bt*x&8QnajfvgYvp)Tcg}JO5U2=xCf@Sg==+ z#zqH+OLXE^g}4nAwjTBgNXaKuL==Z|VpHC_X&*7N_M9xJJs_r+%E7M|-#>JUXwP)W zgxvqH<@FCF<7%DKhxK8}_;k)Lz00Mw?%hjP>+Lz&Q%dOKJNWR|zW@F;>yu}`|NcyF zd3i1$kyBm{`49Tq6Mw!#n@rFcR(y?On!u59buhz)aa{A?Ih&q*?=4w#uJxZ2WsN>2 zBLTw=DA$|e+*!q70&!KUt{?#a6K6x_oy5j8Bjw{p6dc6e?eEwbGkb`gY4jiL%t-U~ zGbi3%y5nDh-@gAY-<_V?zyFAdH)QCJOD7M{s$B7^`P3=CXh2>}>iEh16g)^y{UX{O z#ESlwm!Y##3N{9vRJdBM$IvJ)24uB9pHl7CifEr3dD$nH<^LCVLP|I`?u6Lxbn$)e zuu;=9GhcWiW7yac{U?Guxl#GX_v6#YPq}yQ=$|~<+%02l_Ys4t2KDYbvVRxzhGR$e z4qOt@X2ryP&ylMfip-{Y0nf?qwyVBMkdFYeyCr;wYg9d8nmV$3V0WuH6GQ)=wA9tU zpq_1QYd1@rNcr`NCvMfg{u@s<@!8U&w&82nuD!-jfwZW3Aa5$%2xLzdiBM$`H$5Xfb=uwkiPm(=RQ|@uTBn(Dd<_SHf(wN3vb>%_o}t-_T14K zxf3S$&x83PZ-4%-kLL-`CTj|Zg+`ry=I96a&*p6^7(6m7LifWkzV26XQ+5RI2ePTU zbpRRBgQ2ZyX+o?B7}eqcmbO_&7a>gqcR_JlS}VI|wcPoDzNkQGl}+4^Ik`zY5)$x(nEMi3V=8^e>{#TfmhWc=~9YhF70XkJFPqLa*veAUJVC#N$4e774E29{^^2!ja}EcH5||_zLoFB*`0d_v}o3A9L*64 zdC;%2A^PWuJ$DFnV|Cw%KImcVkg7l=okFS{se7SnrSd}el;1r++`zby;!QNhZDZF; z7h3a!a32&><$}#-7=H4Co)Z|4svtiwSWSIeJJLGuLVOij%o5uLZ?qIEvJs>Xm7Rzs zfXb%fkMFOOr2g3I>YF+YvPY(+^gF(C>Cryj`V4<*?W3>1JTfJINP2woNbkNeq20TO z#rFQP+r;KRqdMozoSD;kluz?XT?^*Tn-d%p6C9F|z=MLqBiaXs1Opy|K z;c-o^uj+JkFe-RVwgw*upZvOh0~AmQxCR&J`oHJmD1v0$sK~}KgT>&*(_Yy*T&&%& zVdraA3l>yy*8x-?o!|Z{oebQy&rJ*|%}pdUHy=jadYmx^kodI!bI$lLD&jVkOgrKl zCwv9(?upJ0_H8#PY``SHtS(E|y|8KBORo&+meeP;M^xX&yyLl5N8DXkH)=GpUqq|6 z%V*Eo{Pc?6W0Ire5`A%~i#uI>AXS%YJWZ?%W+fd%Qs<0gNOb4#jv@J9 zjv>1Voztp!3Tdf#3R%FPO-t<6qh~^wq=tthMHB0zO`G@cuw=_)Pp&z6+3egYtXq7S zzOB3*`5PM!yLxi5X5PFF5H`?Q^v7iLM|+*1Ir1=lhS4w4XBS1ET@-zW@(6a04Qzf9 zNN)t%S${{LJ>mSo(w`qZRap3nb>b=cq1lC-UYZ~ZaqookPJ=ohDOJSv3c$GiqcB}Ae2ek)K(Pn5J^#A8wI;@97!yXRB zqBHWOb&5UuUnh9Bcs8|5V!xiLbLS>?N$MKa?O9v-4s`HS-$Ry`XFk`dJ7-zo+mWc3e820@#vC4!ZOodp6?= z(Y|ABLMZ6(X04alX5IyU*^{*(|GJK3m8t6kBYJy{G$g()iTu{M=*qyltAE1)Kj=WmX4i;9K&6<-Gm;CQm8BJC)N?piTpO9jBJS}ZEPan{K+O+-yb0r_%gpTO9~R~x5E=O@xGdl^_J{bh8L)ns*94sZhSvmH`v)o7 zaNg~dSg_gi{uP1a3meVyL%9#>!C(|2KvKlY&^W5glv95A*2Mh~Xm@~L;%rUz5- z@{S#+UfHqp+$DqczZqX(PZJcjP@PgeQIQJWKiO?b!7x= z$p)i;v|rHI{-w6HA3dbC9|^7f)I($K2eatqTIomYJa%KGbL^+GbS?n5LG%;tVE=b( zKLT-M)&I-tZ}Y}mpE%H_w?5L=U;PJ{O>k=fz_`P98pGjDlI-E=l*N zm>4acV5wf^W%z9{WP1NkX5IrWwf{Er264}8pF)gr<$8K$zjmq1Gs+J{Y#jQ{Z?|Wa zPFdG{)9iu@`QC>x%=!EeYvNDVAADQA?CbO7qnlDv@7!3kab(iu?KMw=w&46)OH}(c zci^0^S?H*YSpP;H+8O3$uH|qkG}cw#x==iS{K+(4J*; zOrNt!rWUL#Kgp(x=UBNoi8zhftcO+%?|>Irv|Ixl?gX|?_GCg^#j;W{%aK1{y-VNW8}W|%euQ|5`Qmx5))0NV$NZ7D#^s7@s5r`Eg+N(HnU84@ zD^{>?$<}J~Q17#_mD~kbea^i3eZcPzHdbrN9y51m!{vHb1dj-r+H|&nV6XB%V#}lx zTcGu2<76g7^jelJs#ux!BHN&WhZV_eFFZ3&7g6~B2{s$wPlcUEr5V;h<_}m2&eh=4 z6m9&Q%kn&Hfc)vUaj>PLf88527D%t*ddUQjrS@^4v8Z=x-C2LrT;$PM)W2vf&a+Lh zMXpeAC)oexGT&k8YAi4gG#0i?c-I{k-fS(>7jf;?P5@sYj026~gKIrY(Uz;{xoSLU zO!RSa)wZw|G$zz{s{3!!=~Tah!QZ8Xqo|Aeuj(XxrFQ-gDd98T&-lj_IE~-unf5a; zt)lKaVEhXDxxZfeZ#-YX7z6jGMPHzG~jn+@twlKNT))rMOu4iD^0P{q~^k zkE5;wY_5WzffqCn2p0*D6)q8dK|kmn;RT+ZAbJq;13)_NkV@b`kE;T-EaG`kD^Z&B0hN1$-OBkF%R; z6#V)ftgEDV)R<0Xn@lgEZ-i&)kD7aE8_h{Y2jdVa&7h6idR9Q=1YFvpzFp6HD%uFx zm|kJMP-eL438bS~uA0jPv&C$fHlB^Au@(o}lSs=|-dXH}p!q^$uYPX{T14}1Kg(0^ z5uW8UKSg^$_kfF&)VsIY098f|=-WCrSPRFTM46_GtUKQCYI>6mFkfZk(8n|CJ$?R` zQ=Tap>ql|jPv#jc!bX2!#1su2-(>2Fx-k~iZ)!W?y~7F??690|G0$Q>6fAbI&A`79 z(+;*?!OsET(fUE(|Hj%3$6sV#*&VC`5bf5h`tq}{}rr4rehvOU@Sl{5PQ!9@SKQz zT1)0@vjN9q=3zD?)$@p+(Qo?N)CTkpbj#ufc+$FZ5x>o3Mdn3pz8N}=QunPkrS3aRd-e>@-&UiazG%ObC7GQvM`K<2ku5fT%N}tIXHQ%1qVCqLy}ZdH z6rN$MZSx4;F5OVJub$RjcdTGJ4x2Ftjd@1(q3u)b^|oMBwLWaL20xuz3${z^!JZS# z*z2N_U2*VYT`gBwUm8DZtI@{GCP%D;%K$fwx7?4uOs)Gtrq_Lmd9w-QF`ves;7{XE zW1w&Y{Wb;R_eDs(>P~B+b=APdG}HSm!A2J?=h;@%Q*6FNG;r-#)VBq+VI$g3_(A*w zXqbj^!m~HcnR;nBjhQ7H^KLy0AiSZmGZh=@GJHRi%{5nI9-XPXU`q+d?QL~K+e*+j z;3(k<(ygk`Hrj2JN%%`Rr0Bw5);JqYv#nL8<7~Lrm6h01dtC-xw1dD;Tz2@{;A~q9 zj4`u~9pOFU9?d<%pZ`dWHmY#}F4BBaIQs@ml|wLhL6-LERNCqpskefB&cN9?rMH|DV&kr+|Nx{^@r``-m4J9>ASFLbQtD z^f##)Yxt_a$=Bbvt$%-)QhB!gzpll`dTCoX|1qt<7VA9MgSDBSOY6cl*ikq@AJ>+O z7qBOB!aij*@*sE;p}5C!G3+zcKM5Y#cA1v3gXV?oDZ1n?_z`OXnufI**2ahU^Q^1v z2H)OM@Z;SXb7u@o)V8tF;w{kOd!Y3P**0E?tH^$fVWO{IEV5av2SX^Hk;pM6D^r6*Rq~X z2TdKTy~t8bo7q9_1Ju8W?FNmAcSvQEMC-b0?1i$le%KH70R8Fk!JdT~xktQGK?H+EMSyRBI91h_;sFiWg1m z-omwqF6smI<)MrE_}7d2PB5r{0Y(HTb)i4h55R1mtv|N5)laF7sCO5x=LvR5pZJfu zs194Xf0q($j@I2!*C%)v@F4z?>ZXey1Ag{rUc$AmQU=!TmNBdV^o#a~6LIyzH3wH2 z_R#?frYMivtW~k*G$t7Djx;`Myq04BSITp`h&1%Pr-Xf(RSbju0e!X`fOz3_5P1#tN1M8 zB%YCjWue?FFGwroD3i2DwEbGOW;L}ltucF>C!4>tjIeBS@O9YWu-oCV!)b@F9qv0$ za*B4!b-L!<)w$I9xbqJ#<6XA89Cx|bAhyBS2KyU)+Az3bVZ&>Ux;8r5=m*z!uH#)V zx@m5)Zj;?Mxb1bjj!7eb(TAO>^Jo`&$IHSkt1WWnRnet@^b( z-|A{Bt8a7PPkryT?$LTf>mS-oXj9SVT3eU4L2W0rt!R6x?Wb*T`U$@#ekFd3{nq*I z^gHBN<9Ev6&p*^Z!M~S(y8n3pT>ldP#s2I3fAYTAUa@jz>R?40!3iM zK<~hSz=FVU18)Ud+c~xKXxFA)aJ%o@-D%I-yR`Re@7F%GeM0+Q?bF+zZ-2G@m+gOQ ze=i8eX+gUsxYO}Yr#oHf^kJuO zJKgGJ4IUqSHuzHTr@=RZe+v;I4MV&`0z$$=28N6d$qp$BDGyl{vNhyF$cG`{hTICV z!eg07Xq(XB(Cwjbhh7W)I`n4f{V<2HCSkr|C1KaXz7D$?c0b%9yh*rk`2L9Gh_r}| zh{+L!5%VKfL~M@OAMs4YiHNfimm)rmxDoMNq=;-7=^Z&K@?zx2k>5w&iDFSMQC?Ag zQK3-@QN5zlqsB+&MwLV@j#?MBGwM)OP1LEVx1+8_eI4x)T^9X)%)pq(Vx3|=V%x+9 z$99hG5j!|`Z0yw7S+R#=D`P*5{Ua_iZdlx7ao0NgcJ9@AQ|G;%k90oX`M3Dy@v-s4 z;y1Uyu6xm)9IExQGEi|&@(?Ra8nVqW5hN$E)^lC|Wq z$s3ZlC;yggO);meN!gt8L-*wFM^ag8XliNd=RFd8Z0+gMvrW(7o}GL4=sCFO%e|WS zs_AvA*W10@^^WX)xKEotL4Bh8bnSDnuetBwzGM4N?K`V)b>9>HoccBH=iP5dae8TvhnXZ{76I>?joESdw{KQKWKb$mr(x+K%vL3Sze|p2|EvE-hUpM_`URvJS zygT`A@+apX&c9#KuV6&Mq=JHivVw|&O$9e*gw9wqmO9z&YF3m12C@m|kDBV=LxAahHW$DS%b92Mz zCd}`K|^Wj~btF;AQ4 zIcJm_VCC=+NZ^XRpc_s5I=53w#*u2Vlzs>JFzkGhh{96l_mOGR$UdR?!EWG!~ z)JLu^N?dexaqQyli|;QfUsADT(~`YQjx2e8$(bb=mwdeB`z3dlvZXFdy_Whd4PBbB zwAa$~rQ?_8E-hKQc`ux&!ORp^beCZEM|5&Cib6wVaS-WMi%X%$KUp9VO z?y?fZiC(vC=dwe~YL=Z^_V%)C%f4QA6WdnTislvVDk3WqEBaN8sF+kyP*GMSnn+rE@-om!HZ1LLCZcDqZceYK&|H5taw|&07>-N0uJGY&mYCyQ6of@2=Q=X-~^NL3^V2B=1Svld)&=p29uz_pI2ndC&em z&+Iv|=j@(Kdp_M8y*GJp+TM)4llKV7U|;yYuKW7z8@6x4zPx><`wc&G9{bzu z58hw0fARix`*-d?w7+Kmsr_&7zqbGD{WtgDKj3hn$pPO39S_7F=zd_}fzb!D4-_3J zKd|b+)&q|ns624;G4IF9AFFuW>G4&MAAbDPgN+Y%J(zv)?I%V*ap+K+Lz@p>e6r7z zB~Mm9dH%^C4!azVJUssJ;lo#-3V-U*Q(qrRKXT^jeovP^UHy#jGbPU)KN@s&@zKvK zT`C7xp04UwwYb`)y1e@3>X+$6LTie6;vQ@qPNoH(1@4i+*PoO{`h4Qz9@!%`)u4#K%Zmu(0jx1ULkw|c8T z4UpC_wq|C*SUN(V#u?+)0OQmMnl*0l_2~{TR!uSLp72c83}fTNnzI(HB{YS6VN=zH zwS{$*KXmE?Sv%Gq9Ohk+IOK?9AeEKGy}<(TydtBv@Ca z;EXF3eeB74vEIOxzN{Z$mxc%)17QU;m<>TBy`jLG;cNu-IWpKN_?{fY#sVY9vrKMc z2cTuQguTQzv+vnb@VF}xf$d557&o&O+`<;Ijog7dven!P5prK+pTc?4Zg!ac%I>h= zV3YGSdy~Dvo&m%s!ZLRfdkgS92b;k)v5xdMTVkdhPn01q_XII%3L>|j# z|3)O$<pchO2U?6jNUAa@eNi2AER^FTsDuDvFF)7wg8x3&K9yC z*iY;Pci|17hS-R^ayM4Xth_N?PB-CASsmt>2Li%)LB+fo_vSvlIW*K-@>bjzO4@DU zuEmf2!R|uyJb(xCcDy}DR1K(wcjCc_ryI({;L0U}N3whDeICW5c?^%`alA8+=Lzud z(v^4Pi9CrX^Az?a`-*qxsk{g8$$RnMaCF|6_v8H$>Usbl$OrMktP;K8_v#;4Vd<-AU$MNwzlTY9i`6QmjC-W&ho9FPUd>Z1=PUm?%pBL~M zypX-fXYwLm%xAH0*>`+4JIG7;9A3)j@-jY;&*uwxIbX;h;fwfUzJxDj*Vq^ABla=- zgniCFV4v}2yn-+1EBH!86`KgMhLv-~)Jjz7;|;3xQt{3L&g zzsz6Zr}(S4S!Xg|H_0CB+3m4HqG!%`5t8f#Ig}Z1X znhFo$DZE58;VpbbbJ0Sy6s?4>Xf4`^w!%;NivSTQ+KKieNOTY#MJEv~LPV$t6X7C4 zM2aX8En-Bhh!dSfyhspTL|4&GB#I=FEK)>wkt%wKo}!oNE&7PQFgfUtaC!s8Kru)R z7DGh37%GN|;bMdsDKf+;F{}u#A2~TEEUT{g;*|Dh?R&#v|6lz zbD?!&z1Sc&icR8Cu~}>pTg5i9UF;A$#V)a1>=Ap#KCxdM5RZw+#X<3eI3%7Fhs9Ik zhcwL+oZ@@+R zo8r89OS~=qB`%0}#6|J0xFjx%E8;zI6|Rl1i4Vkw;v?~~_(XgvJ`6o8lL7OWYQB#INEv@w@m#+!go4pW?o#6;@Fv8FVv+ zlv0x>X_gl0ARVEJ>MUJk185sJlCIKCHkR(PiEJu8q^I_q!7@aK$}kx&BV?qElF>3o#>zO^S;or**+oJkClh6o zOqMCKyG)fmWKY>k_LhBQU)fLgmuYf<94H4telSF)%b{|Z94<%5kupP$lA|Sg20SLm z%5m&Cdybuv<5>+NGQG|o!MeUoW(X;#{&bk4sK&ZXsrTUA z>%q6q*$?iuUK274wQT$`_b$rGos?zHQHiCu(UTmbC%yHaT$Q-=tN&hZy$5qY9YDD% z(fXnHS}y*W)AaB2^zYN^ed3Z=@4=j=f1jrVI4`pxe`Zl(enEDYOwF4jv+|}`1{j^s zH#$E+?|i;W8VtxT&YO~1SUf#9v$&{1e*Gu&V7(26dK(7UtJbBk-h+9t-iAUw8KQqR zQzgzr9)Qky=7W2e^m+xj6xDk$r|ZQOsYFYsAuXaI9jXs$u|A|jjb0TSy&9_bs#qna zp@lhlQ%uG5x53c*eQHo#|H(4c82Vy8bsqkph0e3<-H)tyKj*={IYaMjsY;wO?6~Vx zYQHt*=I2eBX&R87UzlggSAU19zs2-d&F-)sp-xHER=t=^`>iD@Rb^Q+vsCIlU}kRS z%xwKW|G~Y>ka_@gnOW~al^-4v~ibY9|C13BCEX>X~&!kR;nN%W+&^M!AS%7{`#D!*<@(JKBRGh6jjsDU+ z7o$vlw2U9sgOmDL-I`Ui!W@R`T?;d-pTZO#MTUkdYzzwx4Ue$hMTOb#!tHktevP!} zMcMD7?RPqMqr9kCdtRLFF4|sOw5|T`_TOxEg+L6 zhTGd2ZZ9v~-p+7)$>H{r!|f$U*h`MEmmFa)Il>N$2zwn7_BtZ$br>@pu!ykN5n-<* z(q2cTy^ctG9g+4rBJFiNfJ>ykj!1hyBJFiV+Utn6w<_BHMYR2kX!{q@_Ag@Wt%|X? zCC1*C7<*e{>?Oz8OOCOZ9Ahsz#$Ix)z2sPXe`D=+#MIw_B z)fE8EvoIjuT;V zk$U^1ZK=+;Mn*>)`9}YuV~uB{zUU<5IoU{4j8x}~BcoG|=N@_*W3<5zoiIB#hS}j7 zX2;90IHUd;TWYi;#%M>3(T*6S9Wh2bVvKgg810BL+7V;4Bi3j~tU*&^b-q0^)__&4 z0f$%v4zWi4u|~bIM!m5{y|G5Uu|~bIM!m5{y|F!PH0uF|#2ID98Fkyn$u<^oM%^|T z*l^7LozaFkqYZIJ8{&*M#2IafGujYm^xfFIL?#)1PcrIHGWwom^gYR_KgsBOk^%c9 zquohH{YggsNk;uiM*YU#C^E^YKgp;+*?@hrQNOWgicB`@Pd4gLHtJ6{>Q6T6Pd4gL zHtJ6{>Q6T6Pd4gLHu|4z)SqnBpJLRXV$`2v^gqR@KgFm&#i&2UsQ>@#>ROuPCc>Z{ zjJ)!`9p?cQRJd?)RZ3bSCs$`R3ML^A3C3O*7stDfw`%=hA92D3E*#;)g`ctEl;Xf& z3q4==u4G@*)AQ9?idmVR6Msq|Cnr_xWQpGrTK zek%P``spm|AKaU@D1uZGq>3O_1gRoO6@gO(P7ydo;1q#V1Wpk+={QB;v;$7RfRnzH zzLUO_zLUO_ekT1)`kC}I>1WcY>iq#sK^mVPY#*z{w^ z_<+_PyRU6LFbj6=u|K#V?AoJ$aA6Sc&Yt zeP%qk?RV^$@j&S_7RO6X@vLo({9*%bBMP+3}$;` zyVZ*BD{lPdp+SFm5S;f$cvD>J!iQLLli`_#uo1WPl!TI=W;gKP4Yk7FXbhih-0Oxg z6np(w$K&J5_!!m}%cJs9|Mjd~86n_PHTWoS^w_Ru8_bRDA$J#Oy9>141zMDuJ3leD!v?ytfjnf)|i#+x#y%dTa%S*o!KdFv{5jzSW$4htfC@2 z%*g5`-^{93%vQ5vnSPsw(SuWi{T?jS%CmB_X!x=9MZS#CUsG1wC>Vz7manKxr;!sD z{YdttUuoslOTH$XX?$84mXn$3Y@ml~ zSj$#X-#1Vc{b9t z=O`KaM(Vleua5aF6@4vW1HUJ*+|GaIip3By*&2mU6zZApT1DS8*uYO6R<7tX2pc;2 zh}zDjtDUKA%|7YNJ9*FYj%B#bP}{yVs=S?Fy^ZbsJfYflVUF#5j`GudP;Kkde2uNE zb8Hpn*vjXqxy$3+)p0a}8HdZqRolg5vYxxh)|0L>7rJ>#puCyK+}OM-wpj>rGZzcJ z8E><}#XV*${8nV;;CsSzgX-biA33L3+|Mam#69gzx1 zITfjbR6Z4{fmD}C7N>PZvxeIGf7kHW;x r@Ilsp{eU1f+f8)1@z - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Font data copyright Google 2011 -Designer : Google -Foundry URL : Googlecom - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/airbyte-webapp/public/fonts/roboto/Roboto-Medium.ttf b/airbyte-webapp/public/fonts/roboto/Roboto-Medium.ttf deleted file mode 100644 index 26984b15a292a64fcca35b37d2b0ad043c65e83c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183780 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

_P`$b4F2O7s=X*} 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 z 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 bHt4P1jNSpgy*HyDf!^7i(#~XkV`1Tca((@T diff --git a/airbyte-webapp/public/fonts/roboto/Roboto-Medium.woff b/airbyte-webapp/public/fonts/roboto/Roboto-Medium.woff deleted file mode 100644 index 15166091980f02949315d629f1f8eae1dfcc33fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82980 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
  • `#dv{>j?4^GnVpcjZMROktBYNOme07#JIq#Z zV%(6IWwblpvUFx9(c3M09A9SU9?d1i!nIY6U^T#DBJCH_sxD%`6u>4xkFHdt8MRrVp|nBD5pa+ zftGXq?9$~9$8$3iWRtXRPFp;cJXCv7o>2A7H%Xe~Lr|Kb(R#?|Vy^n`rBS|X z@_Z@noyRF-a=nNZcrtF=ifx-dQ-u3p27Cg}LhKhSL^|qpq?P`E6nE zLF{CCxTq6h7Gk2TKhjZWBE!r?g-=&)svq;xD|>HGc!xg9$-EJPO(#G9<+~C>yI{;J zYKWums9z%H$k+ck1zM0S)0C~ereFVtaIDC?$P-d5WyHb4)MKK-LywA}6qTJRn2iO% zsq!CNIqQ4Bw%-2^A}%X=h6|60{ck2BriM?s*GKV0RpS*USs*Bw80(Klv*AuiF#i7! z5?)8tIyTAGMVFKARJgHG4b?pqS_bd=ZctE>QUA-7>Tc>nD3$%_r|~r{y!ka zE&rFwv*ONB5HWgZJ1g{l7B$Kj;Dt8ojrk@>`IdTZ{C@$4x901;-WUYI{{mj_M+p7F z#MnMM&kj37{|g8|f7_u7%0c-rkmu+Y1erv(OG1i-_Mb+^!Qd~XGC}HYHwJ7G7gMnD zSB=L&3RY$(qn9(-4t@)xllraTI-yq{UhsbarOy|)99x^G=noN1;V`0WzXS6~XKE}& z+5WfR6?Z^ESLmJc&jO)WtVx2}-coBaGX>_!clBHK8Y6TMA9c%dubN3)fQJa$xOD6! zFU67KOMrIp|1$rrw}I-`J#RCaXXgKKna}?K{?i@*1NiTr`fn|r)LzQZMc1Q;lDSmDRhO>%EZYiib(H4i^7D+Vlz1q%*oc2aMEmkk zXTDS;O66}sUWj*dB8Bbj7G2f6F`KuZqRpj=gblY}9Ch9XdPSB~@$aoVdhNs56+I3E z1Kc3pwNbN*M1F~b8!CRXlZyH#qpl=#*t1Fs$j7y8eoaCh_9>XK*n+fnV5pViw52d)|w}|JG(VNu1p{~1KXrL zV_E-ZfGrm-zG)e?t}M(#M_gp-fZC0vW$!yEQ3=zK<@D zkJ&tvs){_fUnO2;HrM2Dyc~scl8o|fp-C&5%j24Ju7cjqsal&SL8-pk!B<+!%B;j) zY!b1g>BXIneKgyoOY&f5b4%+X`A}xM3cC}Hyu(5tx3R}Ei}g6t7Y8*rK6w8V>7o)51ITafV6%PjwnvK9Q_Tn=^r`9s3L3w=72Gi42v<%)9!SGGF zC3lN+=aoz6waW_ER@2ec#68|YrH)Cd{4UjrixNuP6Pz`NdaaBlXH83vAsw5dvGkLs zT_f9RRG<^B12>2HWqBa&J_jppej(CO+kDU*WonM$za?C%DGMf+67TjeWo{Z~S zTK`u3SuW``9QvKY$aYG@#)F0B(vzpE;qA_>$6r6bYkwe<@>wmx-|VU~Tb_wXH?cN2 z3wip9n>jUVteHjdzWt}->-QzB7L9|u&0xCzeXCpKSi$Y%-1JLlE$7*}bicdk;>uQv z-1N4WGPmLTn+`Rj;>*cyByB-TiNhpz3cAN@;zgR&YtngvNpk#()Zx!B%JE;k8$Z|V z1L_cqZ$?8r8j@_e#K-KZhKt6~rScypIg8O(x)5he*W;bb^tkJv7I^lg^IcANG>|e? z9xWv8VjRLAv%fBJU*(d=bV{JW!c;wg_KUaY(gp9}yGuHY2sgbirhJnx={xb;9cTQ1 z%rWs#@?-Vz5q%?+V@p3-@v~ry78|Su$Df}4X~~v+ljn%hG&sPz0lM@a z=onjy+m{?4(Jn|!G|!qKNJ1(tI>KOZAaKqhXq1FraS%>UkH@Cs1Z6AhH~Rt2xcoAh zZvEzrF?RP!ZE(N2qMGiE{sjL$@e{I;Iv*mjEs{pT!8dmQE*+)xbG&ps{h}KNhv7S9 y4Ks5^V9#(3%pz>a#FT{ZCmLn=^>jNXDPLcU6F+``~L^gbq2Kn diff --git a/airbyte-webapp/public/fonts/roboto/Roboto-Medium.woff2 b/airbyte-webapp/public/fonts/roboto/Roboto-Medium.woff2 deleted file mode 100644 index d10a59261f0413aba05f86ba90b86e93090afa1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50224 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 diff --git a/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.eot b/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.eot deleted file mode 100644 index a3ae3682aeb57f6d40d158f62f7cc0e13e74a151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109454 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 diff --git a/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.svg b/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.svg deleted file mode 100644 index 296abd0c6f2e7..0000000000000 --- a/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.svg +++ /dev/null @@ -1,2811 +0,0 @@ - - - - -Created by FontForge 20190801 at Wed May 20 23:55:39 2015 - By Jimmy Wärting -Copyright 2015 Google Inc. All Rights Reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.ttf b/airbyte-webapp/public/fonts/robotoMono/RobotoMono-Regular.ttf deleted file mode 100644 index b920169edb7c9c0aa1df2d7f109861bcd0985bbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109760 zcmd44c|cr6wm)8V@9l0N351;hfre(MY4&Dsnr7b#AprtO*t0@N0)*^jF(zc+7ZsD3 zJyDyeF^TJQ9KVi^Gmhh^6^ZowyqjS3Mty{P1 z)H$b4ojP@@!#HEi4PO#d7ZlW#celTCgz+n9kn3NVmtVjl#M_Kt9Kn4+VO8bKyuPwt zJl~3Yb>Ylerna0$2gWb?GbVIY&WugC`Tn1eFvc(7c~fg=b9d>RCR9H45E|Il+Sj9Q z{?=nIV?k|r{%}Y4g3eDp{_qWBo_K%K(FM&byOBQ??fo68!-A!&J32I)zcLp2CF6B3 zFKlma`)B@C7u2uCbNxbOOcq5w?y0_zg`GY9lk)#I23#B%bKbRdS!?ruJbL(#j0NMd z>Wj|i{%*xHVkpXQM~1qqxwAd*H-_DeZw9`K;O=EBd)EEeuO4Om!C&H?@a`4u-6_2p zFQMquDE|Z_S_v$tHvXmb`7W9NV1Z}`f3JSys-yHbo1bbJQH=ghb=+YkZXHn8`iJ)% zT1J1znB$2N#qAZU<8n>5hm?pllp}u2%*=~*GX>tPVohun9(}}5GZ9Zk=~sLoo-oA; zMIw3-Xidf6unv1O)(Ssi!q`-%Zor+Ia=KTqSjmjY9JS)$&>}>u8Gp1AElTMMvs{i# zZ&6v~Oi1b43j7P{E#89bEWl}i7O(_)Ujy0!M%;`lLh5?7Aw}fE4gLc>@z~g|cfR_MN_YA-l0NP{^0j>e)SsQ@rc>+NAQJL2O zhX8v4ivd)Q+IxZT|@=@S&92;*TPI81N*3>ZErclzzpI zA>9R_w%-K&7GSnr&qYf4YXH<2l;hME)v*WgG=T7p19SoM0H7bw1s(jYsr-!L`dd6Z z2v`nS00=_f7*gQP1Ch=_ig(z%fER!lXfHnlPx&HT19zSYK;8TV?wj2{Knjc9kk*5QI=khq9lw^)l52Sqns^h29GCbP@D3ktS zORe`ikw?7yS5uOQH~`5Q@z*x)W!;7GKQZO6+wNPDLa&XtLG-iB1C4`d0Ld}++m62- zUn)C{K4P4)e?yA4c?JMun#LlhJ`DoC!}a4*^~f7i_2@#R+mY5IRUi$APKd;Fca%fB zLYyL=xhUetMgd<*pE5_JSCK04oOnRE5r1iX5zVgwsBa`Y#GfYs^jr@(1R#Fy2hg+A zfR_N>0O|wLCm%pM5_+CB1L%Fq-vl7Kp8-(2LjcO7=R}Ww06p&oP?;M5Do65?1|U5| z@<@Cq+SLQj0_eR?z~ca_v&#n5Hp!8_EqaHZQ{FKE^+yMw{t`q1hz5jHAAs;8pf&>l zTL93BGA*dz#79brew5m2Sb%G)Z#sZ*q-O-ApJD+-LpyCLpXj#)K=h+J?esf`>&t-k zHb_9a4?wz(_(L+510a1vI1|mD1?T~!J6vrk(TISarvP@??uj0hPjuT0SO~}iP(IP{ z5`gfu(}Q?G?bADyw;VvUq_zNK|BjT}r@Ed5ylDf>9V`s68Q>2fJg5$8i&EWvAa{;~pdQNFFARj>eCV8d4l>-(4 zs9v0lNw<(PSl7pW}$4E|r%zwlG!FvQHZ(_ehYwxhR zV}Ba^6W-F_^XWnx*3a+J3Vo;r`{x<7L7#HlJ6*uaikJPZb->Sxq5XZr^crxb&nxoB zTH8KgO?X>Bg#F!5ELuP>F9}V^Kg0%@l6l}tV2*4G+rT&S z1N;;>^KbZ=;3uRA^}_SQ{}O&7d?fr$ND!|>MKEtAon1zpx~geAYIVBU?Er; z>=Nu2>>C^q935N~+!Wj%`o?!Zvy6?6j=}pdj+L671Xd^clfdeZ;A6w;HDL7tuwvs_ zZ3R|)#K*+n04pYK4`2a?fPsLMz>2Be)!u5gIuuwXsME%=dJI@yz6YxY8&<9puxhhm zH3FYemwez(W|4wpa1;x9iJC}9{brJKa2WI^I7m`L7xSF=JlE9XH!3O`OM+g z?{EG3)|FeAZk@kXdCPRmcq{pn)>~1ZT0U*~-^)I&{IufJ!cX%)P5spWQ^lvkM?;g( zNlV0KR?f=Q`v23HQg9-4$Q^@3nt&Q7?~D9*uft_R5!)qR#-Ea@-~)1GPHYmJ3>kH1 zF7R!+GB@T9$@PS%$D8@EY0Q`TL9VB>02av9EC|jj4GUqRER2P-2o}krSTxhJ7^cHW zk7MyH0a_#pIz-P>SSqwhI?G_0&@cv;4L?r~GqGHj$MRVLD`Z8`JteG^m0@gEuu6E9 zX0U2Dlhr^U&1SW%j@7d{tO5FGE_BL#Xp&~u!de;m({^B-?qYkOcOGJ=*g19<`s*UQ zz%H>X@P$3jo`kpRDjQ}`$)o)`bkz-Lw43ZD_9AdZGIkvZZ1!Tg%R{m8?sw zg-+}g+u2U`h}gpV#13%*Tg=vobH(}MJbqGaWy{z`zJpz6FR-nwgDn@EdA``jd*Kxu z5c63(dw^|cC%8BF5%pq% z8#K>uc7Pp(?%2+YI7=GrPkN0 zhpmO0+sqNjvfZi8ar8WnO1@lGrv?&(&1$n#Rb3Nu)bz}WuJm-JZ}MxZudnwr^XU3| zjhR)|wb$3jm_@BRUu~8`n}Lubx2n#p(3s3hjS1-2n|V`=S<-5Nm%43O(PC256Kmu2 zZI+tyTg_rr5b|@?gX%%lJshV9MYm?uHC6dFSJ&5R>haV#vks5^s8hCD#onRstL(SxvkeF)`B8H)7Vr`MVj(tBptL@ zRg+k5z9}kboY;=qdx`I4t%XMe1)v_Rb1aINx@vcpLX)?)-#&mU(lbBx@kk+X?QYyO~IF$ zdw~;TXjR=XNiK+G8U%Z(*{C25UbA2OS)bD@kbQbukDe3)|H39P@g7$F1OtZ|bJu{x zxn^d#$~l*%!CebgBIMW9nO!s{b-sBLgwja^c{8b-(EKw~r*ddelWDMN*i9L2?v3^f z2AMq2H}~imv!`~LQ|bjeQ|hf97Af`74oj3y(+(>r_0kx~tCq%;IL zQW^>zDGdXTl!gOGN+WkF{D1H<@%4c4*^}<-5L6bV1z&+8UB=jE$|L7}C5bWmE7;~~#=bag2*8fjMA%v|c zo&uIIuTZs4T}Xo$q%0mBEYuW2S=2$TLoH%N>pA!IK>MlCGF})U_$L=JJLX2W59%~( zb><-IO1t}5t+Uo)mQW{3sm)C^-i zfUDI7nnG%fxRoiBj5=VWD66T{sWUM*62`VnRCbr-%23=Dgh-w8;%$fDNVIB9t0L&iG1~>0!8^^Qd()L&HDU+i$ zr$*bK+*7GZYfg(Egbb0e3}RURpkc5@XV#(pT$x-XfOhJVaA`0qbQmO79P^+wpu@){ z)!yI#SriL@Ofddmq>t!E`Xy77>K8PD-$C^@9P^17cA^$g|AUC~grcn<<6SO9mp!e6 z6SF}SQW?5vqcU{S zt~IBRlevR#%m!pHkgu|FwNREPWE*j_NNdg*FTI#<s-@9tryG(E!#69Xj{Mb}2Ba-QxG=HQ`{9BdgCEKeDyoUV{FoJ=pc z4>-T<__D%?Rh}b?IGbL;L}Qdca*oLIhC}%F88AJ!*A0tpdBb6Jchg~jaml#774{d3 zz{0LKI#sYthX@BRl{7i(Iv;z$EbYdOk~geq%R`<2${%??j-q z!&5Q#m8DePyPr@-VV2U7KVC}lbGe*+FZ)nzbtyi*w>I40tuFy<$@~B2uzg(M{ep+^ zqVR?2B^HQ%;%V^}@sE;H3Xr;`UDAh&D#cdCEoHT`PdTFMR&7=tQJGcmslIV|*l~s9 zX{X6fT~1e>KAGe&se96~Nv}-0GdXOsY4V!MC#SF}c~i_&?l>=Y-sSwd^Or7OE(I=2 zU5>dt@A9t8?Wz7#^;569M!7!k=H+(6?T)+A{S%KUkA)sLJ??nMd7kwA+AGuRl6Q#r zI`1!i^gbJW&iH&d&1qW2wEk&tPy5o>;Je57i0?aonSKxZ2m5#U@0zZg-ZcH2fCB-S z0zM4571$QIF7UO$5p}=%yPy?8uLpe_>=j%Qyg2w;@T0_jG}kq6X#S}A zI)sH3gj9#Lh4h7N4>=KXCFI4Bw?l4)CWRJ+)`cz(T^G71^knF3VI^UWVO?PZVF$v_ zgnb>}9X=3#ApA`DweZ)%-;3B9u`l9eggN5nh_@p?iTEnQ66qYdIr2c{>By^*uSC8Z z`FT`C)QPA|Q8%OBi25+36CRqNVxJ-ThWBf76*m&R_0-4lB<)*Smv>^rfa$NoJ|8Rr!j5tkmfA@1Y2 zZ{me`kNB|o)cB(KhZBSZkA(Du!9<5d-$ZSqA+aiPUE-d^lZjUoUrl^3@yov>FVb&kIA!=}=rRl$RT)hgM>77NxhC_&EN#}Vtf4G(*2`J%WPP6Xok3~v zF+>?M4Hbq#!`FuIvVF4CvzKP?%6{9ZG|n>)7~eL2VI0X(<`{EYa<=9S<@_<{%bag= zMoi8owMlDAHRYLRo93B1Oj}KtOjk`eO|RtYa`m}}+}$B%aI?{;QQcV5xViC(#?R+!=l0FLKF@#N zfq5U#`+A;b{=)e^^FNsX$^0+p-)>?}^O~M$y4@@_do_nO*EFAL{w9gJ z+w$7BxBap`qJ4Aw#~tY%uP>-s(72#&!3PWV3pXr$ci|TcZ!g-sIC$}UORg+!?9_EW z(WUF!)%E9PQOmY2dwbcRyM^V0D|}WYtSDPCwBnnUrj<8We%vGU#P!VUIob1h&o@0I zz0SSr-h^I5@8;fD`=q|SzBPU3zUTX1@4LM!VpZ3w>;0+ySNmV>f3N>m|JVKB^;=da ztX{mjZ}sNYH&=hX`pz2Vn(j4UtPNYMTYF}m&$_5}nd|b_&0g2B?$Wxi*R%C*>l@df zTYr818|&X&e{22UHz+qaZ%}WD+hE#Iy9tMoZ2EY!|K>THPj0@jC1A_YR_CofTR(rG;(=GTWp2ClpvQxK55Buyy?yca zFSdWZ{mu^M4!0cvJK}bjcGT=>+tIgU+m2&9F6?-E$ICn3+41>~?*^5FK7$d1>4Rm1 z^9H*Iw+%i#_{89ggKrOhGWhLIVW-E=ke%r}D|R;RT)K0^&V4&i?|gdaYdhcD`Q^^r zyPS6U@6zou?wYf!YuCW81G~=by0+`}T_5iHYL{jA)ZOac3A;_ZYj$_+?%zGQ`^@ea zcfY;+lilC$5%zfO3EPvpr)1CUJq!2r>>1c|V9%L7*Y>=!=iNP@@A+=8!(QLL+P#Lo zC3_q9F5SCf@4mgK_ddP%wY?wg{qs+LzS}44bKa-kXWZAcZ(!f9eJA!^*!SUnX}@Xz ziv0uo4;<(?&~>2iz=;E|9(en}t%F_%R~+1W@b8BX9J+GY_wdl+FOTFM={|Dx$Qwt# zI4T_VJ=$}0@aUDJuN}R0tmW9Tyg*?>q(4mK}KJ@lO zmWO>GE_wLrN1Prhdt}Wcr-#^3#8CCn_MxYT-X5|%8uDn*qi>(|Il1qo`Q%rp+)f!! zb)PzN>g7|G({85?r?;NIe){%fQy;tb*z0GcGht`C&kUY<{wzBiclO-bYiD0S`{CKI z&W@a$e9r%z?wsLV)wz~)J?FNaJ96&axohWMJNLo4KcBmEe)4($^SblK^VR2D&aXJX z_56|Z=gwa{|JwQYF2r3hUZ}dzbfNpgz=eGmPG0!#qVl5G#juO17fUWSUR-){-Nj#B z{P^NGmxN0mm%=WkUMjiNc&Y2shD&=c4P7!{dil~jmu_A9_Ofu<`EtNz-DTtDs>@B6 zS6tqDdE|=om4GX{E5<8TSDG-%3;c_*e+a*XeIddRy{43WhDJ|3fTxr5%u*%@Vgt4$ z;6wE*HBbKWhxzhD=O2GaZ~j<~cnK!bwGfT#RLQ|7nrmDW#Uy=Vf|sXsni^VmZu1Cuk(5ljw1s@i|)8W z#w^NU^?1lxdHppvH#b+gHBsZ9oT!k$`9D23^CP_7a}z(JIB40!Th@2V-(&*`@Srp4 zIOyXCKYUNA*&A(zJ5LhC$%4SR$eJCvQkhxm;v`6tqTW#@C=}VHQ_yG@2Nt1}LC-{m z)bhi(Y~|{WzJUSL{r!BW`FNxI?ryHOzo}ClrbqK2ps7j5RudpmBuMns$e_Vpknl6h z?W(<1|G^#eEfzk#dT%v%z}H(}=HD8r+B?J@@-4Ud2}=h*v4gkljn1UoH5J1iZ7 zhPQw+r^n)?eC5OFtI3!>bqac>ixxzMP{Oz%30&%Cl0uLaU9!M1p_M5_QBlhj3bCGv z3b8yrH7PMh8{!e5bnuSm`mk`Fn4Dw~Qj!xr1Gu*)NhfH6l`4+_!8<_o^l%nbo|@&^yjJ+dS{aqa^%4qv#*uLor}W~^Sv)%l&}^NuV`Nom_#d$?k6m+3}A zWm{s-!lH1#s$p~7^s+_U>ua{R8=U_5NAJJ>GI#k5-G(Iz6~+|bz_N~Q^|gbonT{{N zgC$@oQz{h==yblKEYkWH;^5#P?T(%%CIkr6IeMlE)(PYN%Hnd*odr++FO*S) zb8oFCw=Kuio~xlWr#(+I=&X(p(ZmP1xCBxf=*)ku$wQI0JdGx=6-80RB`|@CI6DU> zXhKlLvT>P^vP`;^wxA*=reZ-_d0Iz#OiX!4T3}j?pI=N`V0mB$U1S7~TuAGnG976Z z<7Lw6QF>rSpzY#_L7HNKc36Tn$3@UB3VTastjFk{<)aX}B37rKCP~;`hK!e#nx|oS z1cOF)l5s9Hh+Gh|N|juaY}W!thWg$@^-wg{GP1fMQ(ZkC-#Q33L{gL=?4U`)gNrZu-Lgk0izM zCw(F-^3&WC>r7$d7pc8Db3Jvjaoz!G(SB-uA@u9lQjoA))?+bNEj9^)CTm_NymyxkHd_9~Y^S1F(JQ1Q5E$eonp z?JSURx?w1)bc$r&9#huZ*_9A(SlgVH)x6dap0KR5wKPVk+&l9A)xj43HL<7vWclrL z&d*ui`SNVSa{uO?!|#vmrTUGif5tuadpJv~aD(6mQ5SSPJS9NkDbAq!ms#sKwy#c; z>o1ED@=^cr&SwARy0d@gaj2ii|K*Hsxqr*xRcrm&b^A}LNqQX~eP5%u^OVVxoE#lg zN>SjGv1!TJA`kB18O=je6k?(n>aF0aNjzMbW_eK0JEvWp&X?#dn>jo1-n$2c%S}%n zMBz1l)UxP?WidZ;L!5HmlEr^^onMsc-eNHeTi72^?^NRyr9!Y` z>r2>%lDZ2wU^++?ws^-FqgKX6{31GbL3?9JcEQlBr|5n5p%5>=FZ=?d%m-8DeN1NJvVk zyL)I#2rk|G1CqkMyuy2&N&M;Jo`1H8Q?@C#a0kP(8`wCT@$Ru&c!86wZVc17uG$I_AO zFm{!m3Ld}{6ZFZF(b)e)_p&F~jqI| zErrfW5)DnN%{Rm&daA-&YQindx8~aN9 zCvY>ce4{Am^SlZXLjb$yfL~^*!A<#b^Of${_jUEPw?ta@jpk>gx{osrq4l^ zE749A%QU7bxKfDXk`m^Cq*N#+MK>@}N`jK;DRUeR!u%oA7;{xbut$W()m7!-7wtzX zLo|S*)(MJ87oJE`O%%3HL#l6zg};mrM@IKowx8_IOkIAZr+#Q{rIXq9aIdK&UlU%k zv;fYC*lEIt!h26!)=dj5*!XnU!mFE#6WWfouN#Q1T~nIZSDP@!C)f*o7T9j!9;z5d zWJo4UH>Nm3Ok=o0BKr-~u7XRgC?+E-qb)RGc;*Xbkr7D=5t)&h(<7pSXny6M5CBPK z5GNonL9-jAL=lpqq8ZiR53z1)GOv?0D$C zy|-fP%FA!FarL}Z8pDugsYo8ffkwoB!4rv|anjZTIwTK2uw8`l=?F^% zno=qnJ^PAKKk}9MfuiWnb%pb3A^;nfdHgDLRT?5+l8p)8q97TzzYn3$pICIs6QGwB&VzqXOXrkTVvs;MJL*_Iva|7d~#>D=;t5q(Ca%6kKDnV5fQ~5S=p_5At8CK!e=RsxuF`< z+_W^bt;uPG%p4vYlOmx*NM>@4#u&(nio^0PQE>?*mtX;7LL^DagY9M$A1vk~BRI2) zO=yU>=afk-oQFF&ctnRLz|?RSWmRESc@kN~QZ!F?hwP`=g`b3o_qHBcRubza`WPza zr!IX2va|eRcg=$fkmr`%bmEUk-M@*gFU@d`DQ{1M@Pw#yTF+>VwTpVQ0+J)VXAM44 zx8T_wGh$~h-?FzTcka)wo$4<*%l{adRvw$#d~8u_Qp5Tp%W1cLKR=R~T zj|AqbLX1^{xRg0!o8Y>*)SMWNGW-jRSVu?Mlx+^{I+$z?lHjP3E#i6taq_9rmru&=Uu8d+LZvdfeTk!e zcWOF0G$s71xN>B-@L*=9xceo`wgZ+2UjDnQJKho4OJo0#{A4~SvRAF^`%oYuV)5Fo z?aX`>*fn60o1 z!1~f4$|k*Swz{jW$mXBuLf~WENu8MxT$mBIp*OZZKk5e0Tlq*s`=edy2^Gz;0YOux zUyXYhP87{8&eds3X3R`xRW_13q-QJJGC zIJV*`CKrXsNDrwRm`WvUYh?o#o>@vzO-m&mP?9-_%%PSH*Pkw4Z*;Dk9TpWC5fL5{ z65>RT1R9-Twp9{H2w#i0sI;o|6uoU~vfq2lLzxRH1_dcLuJnRkmf|iGU3ySd=X8{0 z&2ZH$FvJ(dxGEh}>-!3G>wLAMle_=a(6lfQE+s5D($s!_O@X9{TYR=Vz>ul;Qcp7$ z6sZsX_JItA6ji)n;P~t{FK#l9mMXMy@l^rg{sGCA`XJG>>iqWE#P@y0iHmCV2N)voRD9xQis^>OKS_jh+(aFg@n3x0NKcSq`c^M6^s z>sX=B<}XZvI{`xgM4N&6V;|-Z6|9I*W3Uq~@G-MvNF$6)o|JC);-}5am^VOCI73Motg0Ij|^^1snWKt9A_hK5vV#1#=83T)2 zP;uCsB56{2K@5J9U97Y==IzZ`oGvWHTjL$<>w}j)gB&oyB)SF#h>&HPWxU8{bPa+z z3I2qK(gkLeaLpAyJm<=`D$X@o)w=ZNf^c57?a8^8FZuNJg;lXUx~wC^@_Q~MwN=E$ zRxZ$wD$G1)-hqy^d8MfyuG#h7IUNr#O69`E(ZBOhQ&X0qDK|to!2>g9r)AAf@udZb zyxyM+y^+ZD#zdMPML_|D0Sj6Ig&~Uei4qntxkq5$<2#Wh#)Nppgs5N#%i^Y!!jr8M z{nR=txHc=T71eN z{(AJJ@bi()V()04&?KB19eG4y9so=mB+@#{Tvj`q*V3Iyv@YkChgc3c^#aC~->u5@9( zsiQ1G?aW<6QY#ml!e&d?ly`t07b9ob9DqGQV1 zyLN3(E@VaL`k%e?chTaJjwX{Mr)7=f&uf1xC}t;&4G>9+}jBX>Gn?h24R~xW(Pm~PLkG?5B_q>oSJ|`K!e_3Jv{uK#(5o|Gd*NpKpon;U; zWd)B8-{bg*iHQl5sp+hMeQZ~Wk~ap4yyEfowNLs$Ey*x%&-o9*k;)TQ&%R0(+bh9E!whuvz)iUkW>d@2-; zUWcko?>fC`(W$O2`zFs!|9+$86GPG5Ln~|apsugJdgbA{a}Tea30hz0lcvX) zEXdF6D3NC!T<7I4D2XH59-VRK*aPvuS^amnw3Y{sJytbPh5Obtx;a}Vq^w%Guu>OW zxp3tw{bv2D9?ZbF=~niMP zD)AjXFj@FB4=rdn6)Y+Y0j)XfgUl`ht+QF8G4B379t;QDe#c!0M`pS{IX*VTLnm+W zkO^{k&1;+31?qf11syx*%{$bQoW0_7TlRvI z$bihc^z7Qq2p8Ar)PnjYIV}g8<1?2(wlHr|aj0KfE&2yjMA{0PtC*kBhqV0NiPmc5 z*_K))!kCJ-S`1HH3{tAX?atQ6!n-=OBs-Pu_ zyGI3Cv4?NW&emD}A z)8CkyGPgfR{1ENJ(JgI6yGrJ1bR*m+%;8oK2brabLJP0^xh46OCFwODC2hM?g;!*} zi}C&tZYDFeak`TNHSiLkPxX+7NB`Z(Nk*PZs5MbD3A!`Uk0*))%bpy5;kg%H95yd| z?i3%C!tPW_#os>*Mfaf;X05vxb?-&plStD!Dls>qa+)#j)@|Ehb(ALz%o(^4mh=8x0l;MsErq3-4I#r@dCvMGnm0IF0=NsD2^|P`RB1 zIJJkG8+h3}mJIQVXvz4k@H^oTBg;lV6#~Wmpd%)0DFt;olFjAF1sLSyHN;@E3j?@J zo7^N3Zq`j`nw!GOf8@>cg>Of)1mSn1sp3PzBaiHpHV?s)K=DhK*G0W@z_ywfktM>G z!{i}v)X-|4Pgu=k@{o-!{YM{JdiXBIm;dZPrn*k@^{25d;@7}Wl>PVU=}J_e32Q`l z_q&71e>yKTomZIu`CGZ&!)P~nyj_Si^kXv`Rs`Pt=fgqY@Mq|{~x-Q*d| z9&K+NT50ld8@;WcSDrfc%IT;5^wpl(!Tt$hUJ0{$^Xj+NYiGq*qy+fuvV${LG^EBf zY;UkQ>Q~21-R-Z-Q2(K6K}24>KPZAZ?@9DG7yFvD$9~$nDeN+ZOJa~(K$tB#E#MZJ zn8T3+cL;IA4bO7@y)&nN;y+tsHt>w@<6+?-;?^_4Qy(QpS za*T|G;TR$>wd6S~EL=sVzs+@T4O+nR+tsSjlcn6$rH?LHcwFyz=|=LAwuL8`rrrq5 z>#B;Y%8qw+i#Jxqm38I^39dcAI8;-TzgEdcUo#a{A9!WAPWKRdd`B?{(jz`lbw_b7R{qo zR5#;r?j+Vl+>ZCtOJZ=?xOmOb?6ud|8VvYqI@N1>l1CyCe|B$C zU|?bIW_4P5OwpFsjJm@=TN<_G)x&jJi}qE=*P6oemkky~74BS?55Cfz=r8j%k_{SN z9I%W9OC`mW3A_J(&?w-aO?bh-iQE2m{@quE_Wtc0!*&Ys@9z8d#qq=v#J})y{#he1 zyu86Zdl0~Q3`UA8?JQzjYiHK-ldaABlW$yd&>v}Qd9>SbBe<}uJhsdb=N7W2p<-EK zun@NT%>&gr1|j|qTVcwpIrNL3$~{Z7y&}^z{5#VuW9MFC9q8~N=#UTI!J=bEW0s#U zJh(9Gth)%!aG+ba5zu*ZIFR=oQW>P?EG$$V9Te^3<>orsi3RdNa-1u$Lp091=^QpS zdD`HAllNSL;Cc{tt$1mBSX$pCf2VjZ9S2=+;7I>Z3|M{s!}Ei1)?Tz zfk(xzmzPIv`Ssqi8GBz@KC@(Vb83~TF0wRTBfb$?xw6z*zqlp|vWE?1X^Ao#woQsL zX$qEG&e$cSxe+F}AhtpTF*TBRBpYf-c0QupFn3(tLqlC%9k4Nu{?BOQUdXraVr(yFJe#$amyu7z;;UkOnUarTTJ^AJb%Jz<6gOzBx z%Q9P<4q8US8r^GE0Un5{V#!H@LK%cz2`^8~-Q-85Y-qZBvu#>K4IimhO~@LgSpq8MWKBO}8jL*3!R^0S5ZAcQ2*)o#|NSk*xmwt?iW4top} z=s-RrU&V`@a8Z$+@0P_voVJWszyYE@8z>3+5Vf?6T+`m9F961gA!NTcy$J zkI>3vviO=S86O;BIHV=LFrqLJZRUKTeF5z!ugvWEbsvlKsr?d8c3@?Z~~y1QSVEn`E*k^rX{VgSi-ktr^FyvSR^CjMx{>fj^WoPSRGBd66^jk}*SckT~nTB@wuzC}nph6(s3WY2d z)|EN!+Cv&_E6ZZIS2Uh^$+n;mE4RZC<TllJCWaM+?DeosYDowWdsQO-hb;PHM~x zw;bh_`c(N(FQtF~(!!ISX)32J>nVHflIh0gvXyCobkuJH2mA`H*c=yt)E&-_&@)`|GC97sAMBG zn|YfhYjg*?&8_@F`;H*NxU9&2EWUUA2__+S*JvCuez`XZvi#*G3$qF%l!SR)s=25LT2gj6 zLA|JS)qr_@P@LLLG^b~$8(nacrX$VBdy=yGfkPu7h*8_QTVSNu$V*~$P65}2jXXw2 zXsqKe68-aL<<~qg`eas8C*0+sCws3Z3_e6HNs=shwjpTqYt+^F$kNdn!sVhiga6#Jk=sB{U~4c> zRRcG&!^k&fbALnk+2kH>MMN^nK{@|Q7~`6}jn`JJe0F1=J-rcD-cw$-vOFxjd}Vq0 zit;cay!RJ}X3aYEi(aqZ*ALay9D2RCYJZo}*tNgPt8#x=PEOZ;+Z_71rAf+`aSLZH zvN0$G28^4Bc3aSHJb+?0iy)s|+Bsx{lNpHoyO!R4C14|jj@t;<;LNaa(qy2l9N}OO zOm($|XGqyF@j6Tg_h)E{q`O*~C;cSZf`kdXey^6nyy)x0xij^0*$*q2*qH}7WV zjQ*E#Mo!m0TiNCn#6291tV>}x0m=)y9m>l#`T{0N`H5{O7DJbVbejq!=)Sgee)Ka>dv^KDOy%u z-yh~4pH&=P-d(J*n?+0Rgb6}gmOK^h>&mGz3SNPT9WyOMw>c-jLp=KI&KBCnIh^Cn zbuumE<#CQ%(SBK7^G|%`0#DfZKs*Cd!CkN&(xGP{e zam-P&@nM^xz*ljlZ)#$+^E7>P^5#=vH_eWw8&ZX+a#B7sc~alv(Gn^BO8o*^FVPx> z)?^v~jSoyV66AFVtWpYcj>Q(okNLn5G-X?W!Q!?BIa|#G*_spA`x-jR<{t0NG;}{S zw+%6-H$sdJX&Lny0X`Y6Wo<)C({g%FH+5ZEm3>1>u560!-OdAplC_~O?)uX9T+_3pKe(YF}-7pgJK!?c$kI-jQ3>SEI{l9>`Cti1V0@Zb2XILBAq#dNGh;|HcLC zXevxQit11@|bVc4?ux_%nQaF? z4h+5!B8}DEBuk&{D0C-x6ZgjUhwO8k?dry3U$7MJw&cEupFPPHnvSL{8( zkKtgr^D?jakYqP&cR(MT2bAnalA3G|_grQiFZuQ8AKWu)x{If%)&7nFDj#1TRakbs z#;L@j`!yffB4&Lb7&Wg-FDjJ6QOrtF=?0H|lFEw5N%S)dc>IJ94}1c)KjOnnCLf+B z-z5x>vEa&oGYpmkLPXx21)a$k_ig6;H|@Wa+__**UWBkxFt)DC zy43$ntnQgr7Y%D$jSw9;_53X>gyFk>Lh?d0mSgu5(yrGGPCc`bk}bFPBlM4^vb|gsXA>gwCCykDk#AgNVNA5owPEu6_h{!;|2Z z=t*llIf^wmt2*A3dNd`vrpP0|vnC_VZE)AFLG9cbwN+iYu`|j`BU0K@HCbBUZQ9DNT;0ry((p9=`ao8U zukg8P&Ae2%kfh+4WIjDUH_X-4KPTBeBuO2Y$koXOVYc6F1DV{QI*|zcTgxut1E~^p zbYU6Rvp}A9HHx{yCXBLi;zoCj&mDg(lubD71U2O@A9G5US2=>yjT^tpNKH#mPfN`Z zT1O%k)wHIG%gI44sOI31w!@GD=X#v=b|f?uP2H6v>ao59rmE2DPD#t zRT56ybUSd#$q}mqNo+>=lN^bbCvVf+M>)t5&7wWw2zB*xb@iA;VNKpR{Sl;szZ)B5 z;hJO|BeT1~?2|Hf;rXu}rmKZp{QEnlexY6t4rfm~=JuUwYC^Q&&G6jXxWsy6r~@|& zD{kd)jXQc&m0CPQed`!kbevwEncA_ZHoHE}FT8k3uH}0;PiT$1VC?@$2c%T2GE-o` zs(pR1V=VF@KNtF$f?x+F?ctY9a}{`zMuk1hQga|CI!}nQ964c|>`;?D*SUir7@;Eh zf5#^}qf=5sRD_pDu!KP=&vkH7hRX+F^eN#fvK0&8gtsaHzkGoMFe-BQk?ys7gT==T zM`q1BY*@IZJ1jyQ)xV`Tb8l7EzRdou>msxfAw641!xL&(<>&X+#>dz8<>#-eO{huG z>*JO_xH9|TjM*o0);+ieky$b8w+|SP&8pgOShZaUDB0SYk;y@K;!-FO{YOXKX#GgLP_D#4Y!Q*`NaacXBY8&- zuB9MMA02%8yOsuSu&m?!0n6GOmaTjpAk)(Dt~g0JI~uoIINxu%$qV`~t`^?L_#Cr* zD`1Zq<5NX57qFr^T^@sSq>X@$K^21XP(Z{E7=n3S6Q_|1E|kQ-`RJN#Oyw!c?0cnA@?I$zL+o+J z0uCp`QYLUn-a;iUJAR(&J|i-eocwr~EJ}GL3vrfuTI%wP3pYL0+49_hIX5z!`ZEi< zE2F|{9%x$p_!?8wY*S(3z|);8u5HY}5m~XaxO91WSn!N(ZA%|tlQViNW=3d5Wk~h* zHf>dC*=!y$dpm!!c`zbwdt2T1dGRsrXZwYUCArhpsTHwt1!+msr{}k9n?G-7Wc>EF zng^Q_(>hNrOkYr{4N9wsNh(T<_YWv&df?pTY0hqKg~=ru3I0=joIP3#KpT2_@VA77K(G`J6ZR`b1NsT7z{C5_)5)vtCe)oSb~JW1YOTp%eH?4^$K@Po6Uy z!^L@9`V38`kPuUop>Jy!&n*f|3v+YBSCNU2{##!EWAo=d)}M!T-h8CBp?S@HgQd$~ z*;`!=2k!Ep;VkEKJ*%|ki?eGDODeSeD+^5liG>k$kp)QsrlQuC$2XOfZo1Oae0iX_ zc;Iq##oqNDMGo!;s@({7&RErDhGSMLpax)ka_!3cRrH z#Z1V-fTg_{+CK}#5>3G_vtzx{GeiUR9;t~9i6uu)xF#gTktBp-R#m}am@Bcnta?<3)*@j?E{=z)VYjJfkYh9;@xOJN1W8xX&!`Zv|P0IJh18(7B@mSH= zM>tJV%#MzI#M~%8eC#7ckyALid?D+@7x*gidr^%Z8m#-AIHm#7UjTO8vt276jHV6H z`||6bfqP9}ddTWf{Qk!1TAV3a#T`z`_}I>i!7gz}dlIX~7#NVsaTktJU}R;+;v}we z;3ZJMDghkCu^>baD=2cV5N84(c?GHKii zepjX^>M)Xd1{GJZ;so^$dM1QkK4(ZQN%Y#^}-v9puM1(z!!-xi!B%zM6(ILF~~P~ zL_2QTM2`roxoNj3Y{U9~67WTl`E!#J8}cF|@){D8=H^GP^VG!o`RO$7?i!t+U!2BM zdO3N1VPs_C{N&_$`4JKMbM=0)^fcDbKR(36BLsqmePRS8$4P&KzI35jA-F%FGGV+U zPKXIAg+NA;vK|8v;o$NV3NfK0$nwsMEGn4F&{N^(IPrM+f@LG$bb;rLyddU^wZ|+i zeCQZ|_I>Rn*-B@=NwnsI9P-R&-3g~(0QjjA zQ0hCj?`4F#TAN^V15Vvq!2sX~qktor4pLmMS1wq;8MlW)8PO2%rq>v9q zRV>S=I5NM)!ssXYUg4po+$FPC6Q5O@u5T)g3^LTFL=@&1hVLgi$rbjBk1B3L8}>cp z!|CW;saXr05nK;jVd4ooCC+|H^T+#N3gTObj0(Mo`ayB~fxG)&L$8dJLV^(#?G}Q= zc3>7AaJ;`)N)@akn~@-&7So5*7!sUo3d&5mX(jxTnDT|0#-$a}g*iuJXLcLYmds2X z;*~jhW!QJAk=oM}W76ZaiPdR=)6;5FQs+#I+LJmvJBUWxI5z!UI}xH}0tTF#;)$oBY)drDd3FYYO2jla03lr{e1o>JEMi+f60<1g+h zWsSeMr<67RVnQjzUjWS&=+ckGU%*!*RDWXm`!2;VEHLFz@Ok)Sr^1im#pW6(IienS z9EryA$?ARb!HHej{e&TCJFE`3YK{ah``aJMJJbkvksW5_b;VuIXN4i?c+Ej zUa;;;NBiaVg?Fk@1HUaS5kAJ8HHp#rVr0mxf2x`B%8+3BeDOrn>o%=JX+0|Zo{qf4 zW@pQ|@wY7Hm^LV`1Lvo0n;k%mBQhFwHsVRKdyIqBoyTW&myw6+QP_jO4pqJi*%Tu^2J`dea`yPlSgJuPi^X*e!9uBeDHa+YS z6S7}Jrlx&AS9X2K8@haIT>Xa1%8m80v2`0Nt2WlhJ?0gYr_<(Yy}e^{WAM*Q>MdSd zpO8?$wz#**dQlWrm=q9@R2bD8S(qFUkX#r^cEo?OW1>ZT26jZrSUY1=RbmN#6&rte zhF_>75>nbfOT z;D*vS9ptwigp+9}@Lng^jlU-sCnH7pi|swQi=;tC7rmFJ!h8F*hu956V%6 zLK7BG*5WwwWt{rM17A3XK|kk!6G&Lw+Jaq3?CBWT!~);nbqt8UTZ5;drz4ndl_EG z9>hSj*3)oLndOq+^R1e6n zM!#t7?gGy>B9YuE4v9iplnx4IGd$yDM>f+olkKbuCPDf+9g32-nINuH9kGg!S6VRAD}5i9CuT{lY8O zF|fo^F5%1(@QuXiP_p%UYyLIhm?YC4D9g0pE7KnGJWl)nkGk&+jN-c5o;x$Us{*KN zh5D+jwCcT=Rqqvq8X$y(L>EYi-m3u{aOlOxVB_vUY!kD%C2>jY#IaKxC$HZWr#Okz zi&Knt_?~lTb|oR%PTqeXwm`dc=gys5PCw64+t7TdZ8iy8_}o()$K0!JXzqC%%>6b# zXVk_qXLt6qO3#Qa3UTDLq9HA|p&;{xJCB4o{Pp zmn*y+Fi9d}6wyaK?a2o+eUX~?gx_qx`qjkbr>g&*ko|P>f5mgB#T^q;pu}@_`-BuI zWj3d8kh#yW{n&#fIr+F@gAqQ<>K;Y|q9~;v4{gAfr)i#;VHk*Wl zjPiNu9BTQzYEFh>fujxP^)O=V)HZ7-^#i)8J`3YH&DLve)=z3P{;XAkkJ=CR0`CV5 z^t$kEIS)2_Iq~cfureMa z$rl$Yi{=l8Eip0CC(*~uqZ%pMgn}ArLBs>aalCZ!!n3Fi*29o_Ll9YpPQ2I%y zmVVNGBzNhN2O`o;o>~UVz1oP#V@+Q^v+b2 zlxu8O>Y9z)3bk~Uiu^~FKPN968p(OM;(Vo4msz6bq~z@?8vB|hS<6WQt>v-z1|!xc zU)u-Iu|}*7?UhDtZPYft&NiEb2U(rgrfyQ30!JI{gDb2_YtuBT&3HenghaIs*4WX8 z$E6#>&=0sR_T?sFEt{wHGmrWK9Yw8Jc_GfArw}4!SW}@5fRYL*nuwG$5!v+MeU$3Q zr8qAybQ9tg?CXu@o?fxY`-Gd(%jB>ekr~tnA2m}h>t%kU*SD3FY`Z?H{LW@$evQL* zQBk!cjk;^f`^9T7ELd=1ZL#uod@8g5B(ZLBW>#NAA~wonunW}d{jrx?tZqnUk|W3# z2C}TXl4>g}Tl-7ew$F`o_X+eo?;d3I z2uiV zW8w@jZqd*;3+@z2hZt0yuBy(%U376laLG)O`yFa)3JaLf)KJr2+g?^$P+eG^mJ%Nq z9T^rfJHX%9%frSvv%Y%HwwU-0wJlrb#w&)P{Q0Hk{A9Cd z(#)ia1q%{O;{4!q_KnT6|2euom=$Ku%?ksPk#Aj9NM>w6Letuchi{yy@19fVQZdvN zpOu-Oli7Q4?nm=VffYB)FTnjSw~#;|>CKqZj+Ba>ktOM2W8aDoVbPKK4e?>wmH^EC zQOF*M$Hv?vl7(cCI#u@IvA(*W<9mET`{&q%mB)SR^`APgZ`$gwuDZXvru@3z;JD5@ zwg;-$11DV9jo-gY&##NuwCmplU1`&O3-|v+ef~?x{RbtyCaL$U*WXaDd(!@Woby}t z`@d-S8L(%c1S#To%Cwv4Y)rZr@3ty~w?MWMwGf3G?6)}GU%-zFg;Z;jKeQ-T8yyuH z9!6k=uB;lgf;>G=kUTJ;-0bAU*jQ5jn7{Y9Ud3sJzY*Lc3Riyl*=1-RPq}=AC#UIvOWnQ_>gGCi^e8e@4 z)K-tQBaJ9vFFHe@%JL>PL&u^c@VccwY3cN#EN)Ha0V0W>9*J zF?aFqnxaiT`PPvK`}jPNjAhZ&*_}&s%oc8;lZ!c~lZ$!cade!9w5e-wXfh2^uhY3! zuWwpEfr2>h=k$YLXB`_S?;(Cae?DC&*=X+++HvPIR;d(7r5&IRBdEaGDL;$fJOrNY zj`hRRNPSo%3gLtd4>hYDl03OpWnB{-Fu>kaQ_bOSo1p(s)T!jou|VlV`(=j;bQ3Nnnl3m~_WlOjyAP7X8zZ%373hQW!X5e&y+ zhStz#z-i**eJpBbh9j~+I~`s$Z8MQbLte9VnEq8MM)WfwB!j8?A&*haU6NR{Wy!)N z6sMTg6JNV!N#Al?N(!47Qex&|iUSFW%9GjU6uPK}Ec*GLc&qNCV?1in$LsW4HGe$O zeP6ElWe+b3S!_F#Yi|mqC`P_tcpQ`NEvz>JM2IFFoN%(R-s<%?o!2*wGIc*Obw8=s z|LVBTIyUIk>$-{8$M1&@Lf6G>+I1eEqoeCRv|n)M4`P-1j-@AnZ~=FQ;w!=X{h+S` z6N=JrCd60b*urS@siBk8$4ySojX^xBGj1|##f5?Xb2&C!_L=^r_b<=lsTJK@qs^Na z)~~LNP{SrmitHa7zHEQiTJDUSEVX}9(yGNxV%{dd7wD1CKCibCsarD8u+~=u% zaA6O4B1#j-6A2YeLZLO!gy1%$6U#F|A1Rwcu7$-)W_o!sR-ypW$~-?wbD-4_JU}4w zD0sX(T;E8YAlrsN<$S0o zuH7+f=FE&J7%?K;>BE#q<$Rw zDDQ{!2;L9coa7W9{WxVzwVxzsKivY7q%}QcQa`%)(1!Yft2Tsqjn<3vofbO#=oB*9 zTCI<@+WuF^LNbfmM`tL>BT7$J2S6+qbFB{||Nx&{4dH`~kwhLJ)oRl-0wJxk{E;U^yYQ1Om6}L5L<@ z52_WRy6E-L%w1i%rvM=aE-nnZ70)t;H-++YET7(((+L+BuGNDN22E-^-X|RJJm`^n zceI83d{$yS;&;7#5cBTI@t%Nx$ej@50SrbMc@QY&m+lA^a;C@0AH3#FjMFmZZVR_< zuZ{KHnI$KG_g0dY9p|U!%Q5Nn>ClI=Dnr|_ zpXzAO3hUflReI}+jpFFTKs1~80h+DjG@JTx&}>!Cc6Ic@y7cX8A7uP<_A%Sp2ZW$0 zwl;MfKXmrdt;*u+z6WXiGUzDb_?UzeYtbxFdJk|_MB%x>r{aRO*Sxb(^WnBdm^Jqr zNfM`|H8R;tjg&yg?WF*vH2FP&OcXS#8U&yT^04=8Mjm!(L}hhH4JGtp7JyBwT~`gHhW5=w@(or#8}ln zXdG%EUH_OMZ{WJx2hn}Ck8bpFC*9|LaJsMd(fyA*#-T(Lu9Kq=X_@dP&PRtjANPRn7aPc4outjj+9_v?o*1AOa-_-hqlggQ7k)cvo1;$ZpLcn<(@_ zF4(#ADuA1YhY7lAY)ovkKOrAIIwlZ`lPnx%CgrEhWIqCr0}}!1dIT13yh#B?b?A zY!Xi^f1I3N`SjB^<}H6$`TEo(OZmH?x3q6)u0y#^UG*O<6xycP)W3-~ZMs`n53(PS zZg~T9%(=N6Uk*nUg@~t038W zBAr(I`J1C3)|FABj;4gVK|UR5Ea7XJ$Q$Je`sxMBCDsD-*MYQU!2C*`WKZQ;<2*{Z zMhEK3iK|Lo9k^T5Q7Y^bCm5IVzjqL&=4xfxI6l`Mln3OMBX-dq{wBsrIj)ogUTH0x zzztkod3+(v^5iQ6H7!OO|FjGtj!=VDmOuq1h97j#Xy`G%MOWXa^vqByDx|qA2xBtNLz9dMv zO=`ASAQUE~M(Wm(u*BU}NDNcmj6sCkHt8a_Opl`zA?Ymw0pY4K19s_jlQUnNtOVR` z%yMluvCC#@+tpsPr6cVojLZd59ssvF-m;@3$uf6mdtX;jY867sU?po-8i57GK?dmfrbk-qiSr59J{7~JlsOyt>xgALOCm$ba;n_5D0f+I1R+cpS`?x%))>;+^rfnId5 zuTJs3Ttkla$GYEmn}K=5+X(O7zNJxvTXc-Er=A3&5-{e_4}2kz|Cd2}`i5omWiuD|q(n=(h?$zhW>Cg*~epol#Y5%p>=GW8)=N)Nn zavkXKOp5iPLJY7FK+vUhDGhZSVmQ}p5QNKPRipiMTyiyJA`g%4VS42g0{J_3%qBI= zxje`I*ZagZiI)>a0@xbQLH80Gtuv|AgWA871ydTR+zAs^(WC?rN=c{qePoD`%Su&* zICy~{@zI~N(qXU~1qu&XVc)@N_w`aZW63!7Gvtyk0bsSoT2U<*3>z*_H}vLC*PHpm%A z8|s73#_=g_)UlBK%Etm7`=crHEAf8|_bu?Tu+D!^($jC#*|F&T)#o7EDBu1EKKECV z-xq?l4Wwv+*}guo#1d_z$T+DM+}7c#Bt3?kXVtK-Kq1h}FD6ggvosFAdHSq}zjtmb@2u&acjkFI> zcf{yg9PloxkK5nKHFDC*b!kqM2?cw~4=Zzv_Ez+sUzMM?@_cW_{vvi+8DSmDqwKW3 zAvJAwT3~KRUML_74KvI3zOs|Ovh$U_ z3G;gm=O95S6`F)9YdIhLzk4;zO!}i&V?t{*P7WbiI5pWvafi`+!Q^#Z)eI4`{n4FG2 zKz}cA`injkjb}4Yv;m$0+E5>$(YJp-g+{AmDRlG$W+bs@?QA!zXPfzAys4Z<^Rckb zUrwUYDi$ZVG3RRUvwMn-`6~8A7JnaXd~RdjJH^J#F+I7hg7*Xa@!lym0^Sd|Rq%e$ zMm^sXZOrSHa>541J5fLIgSY%sl?-nGlS>9f)2=ENIZGg|E0D0m$QvJ9dXWC9tp~?P*s6a9vJdXXy5_SB!hI?S=OP{PBHj=9qlWUse&mF3xOw{46by%3r*9I7 z1D|KIiI*BGG0!|c3pRx>K@(8txlQ9~s*iIFZOBJTc85KPk>iq*JKrQ&N8XSAkB)v| z8%||KT0cdT`njU@1G|Itv9{MfcJ4KGJVlOv!21%}-C93)PwMCIj(*UlR2@wz8aT#c z*x~GBzL22WF2ElhHfH`#dh!R+JHeiKyOH`3uTfB%*2h7^_&9omXQsrGQ6Jqp$2f?` z?wjb{#RLO;R@u(6XOobx;0DBC5n>QeSD@@Y%1Ph?8ZlC^NBHG%4>2^Jcs`r=zH|)I>LAta<5Uo64ubwynKu zT~|nKU*1HQWMWsG*tqxFk|}t%&%%yU4p}LIywnzd@VErXec13KL{gaN2WA96EEZrdr9futh=WL5aDM59y0lUZWBe6 zAnD7(4lIUx7926f(4^%@bmZ>`8W!1zw@>!>tMP?ZxX$AX(Z>k(r`kuCwtrRMIQ7AO z{%CVp-8YO!1@N(`{e(IC5mwzEQ~SXlcJwohv1D`pX{GT($GLAx+~fmjQ^?~B7HMtH zVOR3AtHu{#udDsc#Itxmc;}cYv6X5+ub>U}17Bp+-2ag#?(nLkUY(wpH1MU5O|_bOthM@7dgoS1mqf`&=bZ5 zH;Z4owB!3}3l6kdno)7qk`UwGHlKazOL?o#ElTc8HU?J3?%vA2FFi44T5zm4-P8Ak zi@U45b(QqfqkW4`F3IrsIzH2rZ5c&~6Ups;pgXVYK0$q%+)9kPeA#62p7@J+>5}rBwG`JI)NY% zuv;EnO<^$(4RSpC)nWna1ihsrBnhdB@PmzqB_VEOs`R{p0+1HnUznBtDC?eQiTfPf zwERr3rE@l2jw*j>{%63aacpwk9^G%SmcUzpfB=QdLGDRfz^;5&3O7&)VGW1D}FoPG<#tPFE}+hkd-;>KZ&- z5709XjYk=O0Z`RN9nh#afEy|77&g}d!QCca(n65=2_kikb1*}?&FWT-$~!gGvwosKkGC0lWB0F?(rT%W)|oh**I_MeyiCy;c;IyrpX;+ zM0j``9!umB0NTXkk)%_gw-2M0DBWNWYjm5(Bk6yDHas3lI`yx9&@WNC){h2wPB>`A z6Wr!>SfjP?P01OG$9{c`$A~_mwK;>lLl@*_U85*dJ{F!kU?6$>KCR6bb`oPj?iM?# zjfKbN>3)nhFA_Z#HZ}XIz4)qQS+7J*kp0OnbzS+k`qs*~wLY%Gk2o&-Q=3Pp_z~-s zq;a{O+qWK6eyH{HL#>}9XycUOsSVRjZi78UYY+$7z({g9=&S?DlZ@_Ifl1VrZ0j6P zVybN&R9ZAUE$8W3KB;JbE#P3*#mVdF2=eJ{0-H!=}aF^)K$NYTS2q(dbjdIpW`? zgqHP(^R%pZfd#r_0fdU*N--{>YZO&wyA!9e_m12w%I9W z<5*@=%WBl%L5e|iaWI_C4M@-L-O-5+4a4Y39Sp#~T=tQJR4BnSer zNUYZY_E88DL6(`6EpqPE$ul3Xk?pfjpAP&J`d}&YFQoIl59A8KuZ09^^vp)c8jF-+ zM-SQQeul`H%yhB;^aIN9t^0IsXT1OQu^)zkKJw*9q8r9A;2)Aq;3=_Rsj;gW3-HD z${xoJ64|dPVV;ZXz{&6Ya%4>OM8GbY?|Uswg!|>Bys)hLL{mn*IVK?}A(t%;%c@I? zD=RLE@iPZ`>AsiPS{OCUZ?@m8lB9sdImPDC$WZT43&*Jwg@4FDmwur86P{`i9QZOk zIT6n$y`0knL|6ilKT`bo1Lf_Cswhs1!Xu(3Dg7woqX$14e5;C@&S z2+hK>@lpf!Tic&`T7Cg?KC>^CUr4diD%h6}!ZTXkXP5B3mB{c3B z->#bw-)@g_9QfZk&N~w=@;{|S{br2Aks}WqIQK6JsH@>A8j#RH+i3YKk9X-eE88#= z%m@4LZ~B*U55?S*UmSN})_8p}5%8s=m?9C<5e3>CP)-~jOdQB0@9w&{)*n#bMnOu- zPtIkx9KY#bR{k}}$7!`DY5ziQ;IfB)vnqRF6$h2CkQ{(i+ZB?(R0C|7tvMvectE~5 zqu&gBSA0KgWo*#?A+@`0$M+BFx8nPxe$rb9?cc{*a~)447ENt_k2bq`n`EucD|faL zT)`_xdH-XSU#r!j#iYIda4ty$-V1fmJ zY6RjG@cdmZLO+FKuQ^ps6_MhZ7^CecnDlfLwXV>qHN~U`C564ie5X~py8e^OVkb^N z@_(r=ORHS9*A?t4;i?ebyZ5)Y$UVr=_AZlG_>nJZ;_Z{7n8n zm+`zfJdf9%!uxQa)x?+blnnutIjQc!IGg<=n{=192{B(U<9^gXLVuVU%+DHp9zuUJ zNJ}L<^b9@553B_q!wKb7+usx30nmE%3|C6T&va#Ei)PYnr9cWCW9(N-ko1;)HhV>U z%l^$X$HW@3>ew0kxB0t3@ZvJNo^0nB3#1QiEM#<-fKw>Q2QZe|LKIdLwWZ?Y!o!R+ z5lV&^g$RhnLp!Wpa1f`Jp=xP3zet3Ca9&~I(@j@MP0%N?2B=MErE1N1RHeKnp zExxk3ynOSO#Wp23s-nMyYCenKi>m0eTKg)Z4M8XbN4Ky6gn;v(?Og0F_K@PD_AUf*K1Zn-|%a!dJn$X8D%AGma_ zv+3~f9_#6O?01KoI=}S5fn?xBInFTGPjQA}FPwru;Mgk@@}sA-JMKa*@*(|p(080l z(Dy+P%9%o54&@r653=De(r?4{lj?Qf$$5?sA)Yy&-;Z(8{lSxSu2lZ9+{r%%XZ=~# zIB);i$v^JLGm1Hnxx)Kc`jtC)4EO*aC;YDwID@aN;r*US@R1VYMM3ZB2KfZw?P`=L zeJ@Y?-a7d!LekS5;Iok!Aaw(ZO_I`)5rh-V(*jaCW)_83!>-qw+&J8X;HIR`paJp~l`K(m?^TEaaRh=8mJ}E$muU=9djL^RK&FP^t zW$}>T%(B{w>ZZdlukqXV?)i@TsvY*5b^DhTw3diIVHsw>$_?j9t`ZUFxf6bnR}q7f zC+x7!LNu)u4@5#A0J%}X2ce}#A-oPREukzHndDHcOyG==%jBuVmlHX>AmmeV1cLv5ECdn)f^R+7n}zWQV(eLfvyG>NS+{69Y~$LOaNqgQqLV=s(y}aHxMt>v=>+O z-oK`BamS{8<(nT~+;V@>&8kh8I;;x|Lc)u>^Rjy?ViS)oC|gk*8&TR*cvSal?y_U; z^G_!yd~MH)E5rFoX-cN6Puo&V2 zRmkHz1sjMP>Flm>{SetADH(f(u|$;f^H${=MBhYufn6H2r60beWZhIUUt)6u0%7F% zSV?6+kma#I_ksY?+;7A=7|;iU3s(uiDu9nsNN@#60Sp`v?qL-M;{g;M%;%8$9b!jW zX--x|cubUzBw?qe8kP*6{Vy6PWc%{1Rm_qkA5CrN1T4mkmdudVclW&Ji**)badl&C zTt!;2F{`uee}7uO>*o56&+jhJTCk&9POi@ijW;)KY=sfToY*>2)v~cUR{pqRb$x8I zdAF;-&rIK_^f3SAloVr)^82^_)_(O!OUse3uJvm_v$567-6yM}#h%@8Xt1zw@KA$a z@wR1kGg#rW!}XX?PG^8$RDig%x)27K2H5TOK!r7|!OW1Zvqk{q4e<7aJ{(4#yOB;) z&5vcOgfd+Dxv9zVi0SnAoi!6V@&&AbZz8qM8rN#mxll&Q@)Ph~jT7-*^O>Kx{N59> z4a2piYg&?QET&@N$_)i8pWRcvc6raT(k)k4_B^qxp4pNcm*&;2tTcs|F0K6=`$@}! zXlrs%Xl6xBes5iNv{(F`jg39q!y-4;HI6pLCd}DT7hRkf7?@ZP5uG3B4*`kx(5SLY zP6qFe6QZpVWI|xIsH#K;NhmlJa2rc5Z(K&Xc!|z~AK=`Plo-aq#o;34+MPKW3(7e; z;_T&QWw2s(gJpi#kFyq4T3BR8aq!~Qw7TZ&ojY30aqau(vow2x?%GDBt#owb?#8~w z-f1%elj@3M<~3FL&&_H}h|KYf^vv(v+>(3X%tP(0;0(seX*_7JpV0PYZ!)-1JU-#U z8HrbR^I9rc3rVtQdq2n;L_se&3UnQ>FzKpVQw7!}iow?tAta{+hYh6?Fpe0nx|!LJ zujx9{pLKKRjwN@++*AvyB=lVzx%I4EeQaAp$=DBZ03id}aBc#CXA8R(G>{gx6k!PB z5eamGgi21CK%>Z{jnSl%U1ZAjw29X{t*((6o+XOwhYoX>6Iug&odTG%2+>{zU62EE zS3fW~aA_z%Z}p{tK~&PUDL$Ka>{ze(us>|rxnqNvc<8<34GqWNJH*-!y?3&q;pBUV z{&dgHH{ZO;qITW<#y4(aV3=#pFY#J_q;J5kB*DH)1VFQ`a_ZtZ`hL+UJ&pPEF{uZ7 zJXO`pbVHoYf|3hNiH#waqIE^pYn$Sf2M}uOQc@S~7VNb;uxv~hG3mNXTY>#2?LYFP{Kj{f+l_ie-)T77^)kZ`ePUK@oCdd zLD-N!!I}xh(0Nsx?D4CFPwBimHi{ood9c@ZZ>{5YjIR59k*x6=(Pn`iZ zCnHhRT{B$s`Z-2Whx9yPbY>%lfWk~-Bm*;in;p)c6_Jn~F*9~1^DdZOy}T~fgDrOp ziHHkuadQQ{yL;4({P{Jx0pAaiU5-XpWSL}kMCX>((i1yYYs#^pV6S*u?;26oUn<6L z;4-L&--vy)nSWl4eT2Fl_)M6C4Dm=C#bY?fLBa}^R=SaqSUt=^R_z0^cAOg`r2z<1g(yiVvf3FZ zGZoAVK)alDNtQX4bWi9xx32c5MCE)Q-Cb|BoXK=KCV5*lTxji|z zt1w*of^Dz#H|dgnMM8S8i>K@EaG%hM;kn}Bu^#CXj6I@o1u{-0=)OO!Fwk_PAc24b zlRs7yKS0(sr!2%iF7?D)%svoB2%?){Q@O;Z`p-i}M>QT9GMie!O|HyZc79;_gZZ|a z9gi&3oTvVklI|77~mKkS@i%sG{|D&5Ku0~ZZuWA{si;VBQYyP}Li!)eKO;=)r ze^zohTeEWat9!~yw?8L0W-j@{g0zkjwMb|AmcDYI5S=`E3PIk~-uL2L-kNx70h#Ocei7@gd#%9p``_M@&(Uw?#=#k0kz};|U5t|&j z!(6E2;-9=<`Bm>=$(Cn_N1okUQnK}#VKIB`fvB3b4fShkBh`OvqNGdJ-`i{KyK!V5 zl?C%(^U9G{`+LsnVD$%=78Wi&2swlaPeE5q!x(1^KtUeg&T3o*cETj)L?P+gSS9D4 z1f7CIo>%uyQ|@Cy33;Z3h9FC5eqMek%3H-MXQX}71^c7cIG@nw#Ph@W43T3BPt@iKCk4O42aSwa9T5@rAV5(7l1MsM)XBqHyScKjpkZ}YgjA97 ziqR78ow4TW?W>e8kyV9mS!A3$2a&`*Ty4J~V2xl`Sj?5{-a5#U7aD zF?jmLfybFo_dd(wWh*nRJ6Fx|7N1S&tgy_z_q8=kUN|%8p`?l{yjzEM6;~cwRh|+9 zTD98A?-yc_Oz2f&<(+t^NIEkSe%=IA$Zbc+p+XJ<-h=!95UgOFJzJezjF#rr-<#$Y z!$+A-r#VJ^p=O{sL`*fm5}us0;>m5czVj%`Ybu1!>_a7B@WN1;hx8;L7sa$6#JEyO8;a)gG1>94-_{uP5Juv;T@s=S zWKFO~+>;`tM8y~*ePUe5tgjborb$dAOOcvzHa_YJ@zq!swl*Fx~cE zW$en(cP=kpH88Mh@#XIfU12imb(n81)9K!D*g%9;K%nFCiJFat?`wXY+dqU=Kc9SE z%^`q|M#~`>be(LYQSB#WV^QrVgTI?`Kf2lcQ2QgVWrCs25BN9SR)Ql%%7dSLwydFO&Bet75094Ij4EGT zw0`I6XLeMkb!@I}+CDESvOL@l1#eANZDU!BI1=FUz^cdB6_jjvbdWWQ%C(B21`9iR z>S52W17Ga-XhCvJ`l3S}%0+3W3u`SNo?q(8=B--Z*^hHWcJhaG&kIq)POHak7ij;H z0p1=k2Jq=3X_!|~Q$;&iGeyw?ey&Qw6Rz;tQLm5`JmHG-o{3*NnnM_TE(#8LmE9JB zqoU+5*Pgh=frKd15UB=$5k<|U+`ydT%Glt{ApcpRk@?=r4{s=I$P=G| zH3GRXz+Yg{ui?T9x8lbm50i>gkR}V}g;VM4WsHjPbTuH=GIHFgqe`iylmi7r0$dGT z=Gwt6L_WECaOG3m!{b6qRy5);hHvU>Tu~BYF)fpq{!vUeD>Kc>qFX>rXj$#e+Om+C z05|E<@>_RzKDe!J)!@MDx@`}3-hFHNS^MZ#`=(9yt@*3wq&!q*sx8}ic}4&J4DM$FaHux7d=%oZ~#rA`U*!5r!B_I zpThDj7b-$%Vc5#Y))l<@6)~?R)t~J;7+w&1L%AaR=mL~nQMRssV)^UexfjJ$3J%{d zi}n^>fa5chCP^ zXfNLQ)attR&2eR;mloEY>FBw%zKkld60ha?7to1{DMk>&f{d~b7`_e_NKv#%wU%J? zS{8Mv zt5tl-C8>T{Y37oqWLDHOl$y1AprbUp{m>WNdv6|}FTLoR(=k$>wX7BJMP>7g;pwOx zIJ|J-iGj@G;miHSgS8eUOyw1~7sPsa#phIZt|(djh2GSHwGS>WUse+xl-rK8bf<5T zfBqal1?4vTbDvNO7^Vm-jv(KMa}*5A0iw@Q5E;c$1Ovr==sHo%M(2;reG2cQ%0)(2 z9})r_AWKMWcqncOHbn!u)lCl-M5})SMFfsL$rm6iun?!Gc?TgalG_6@n~~!0y65hi zmyj@T*IecIud%Sob#3AP)!ER?GrAKBk;!2$jMrVWf4ySE<%J6`Zz$IV*nfXR`QY`z z(=4B*iBH;-?KjfrEX&SX+M0&3@4?s)W9eT;Pj1{`Pp76=#C!Y1RisO~;s*QaqMFEor6KJoNVK__iE`b72CQ$~B`Kr-&(B!Eo8o5ij!s^d`WS~IE)I$WQr-9BGQ46EP zs7FY%Bqb7|uqyt+S%H1`t<19p=XVz7WZ0C4B|At&0hTmr@tNh22j3{~DG1Wr%RnKp zryvc=4;f}b{z=v7!**7odXZQKd6CfOGTOuuHZgmXx2e3ndrE$MJoK0AgjdAgr8bBj zFipn6z&l@7&T?O|yAWv&2l1A91Ra(PrnoL`$*=_Ek=6&s`*460)o*;+Ci>fy`)tYy zc*1|JoBc_%a+VF!*jg~QV|;%jJ_37$#tQ$qK$yhPtAS^N93uuyVi-dR&K*zFl1TWR z5+rd179I17O^swnnpIL~@GBdKBbGz##msHpb<*^%uY+rO3w>@}TN@c!yS5SYTT(D| zp?A>(!w7M(d)wblY8=eX>8pvyQ?)sE#%$m-r^z&CqRAL@CFW%#AG49PKWu3U?`1G> zPLK0Q$uCIk;^z?sRZ#^H`B$_@xmR5x)N>rzs{BPL=XwJx*Zj_!`UGLgpP{@^yPFcBK||sSA;a&%6hKo ztqS65HLbu3|<1Dko zBikKx-Wk|VzA*BA4PHEFY2DmfyrwnP)^yxV)iaB{EcMK?uG{~fk{m^cV>F$Sc8ili``C zWyY~l(Xx%4;d=>Q-~(QI8VJ!H3Fk#6{$4(EyiMsA&25MJ(_;tPWEvER`mxLQFLs{> zP$Z087#mzPlVVsV#RlQ}q!<&&yYTa}i=U@SF(bIX0z8gtDCoh{=)6H&9gpk4ymH!v z_X?!<3Lv;jfsF2=Ho0JZfEi$bgs=CHiT36bY=l>lBpEG1UMudKT*a2YXaB7+f9{4k z<;wyCW=6-y`y^FnM9qv-X1yc+^JQt{Eo(+kbzFe^JratKQ50aCTts84z?cwAf-}FL zkFgz}C&p?#tX$%;SQ>3)ax0b}D^F}#2kGylgiWB0h^_N7J!}(QZO6SI9(!D) zjlWlPNU_6vKY?e&;Js%PB@Do8qce)=Mz|gn{XY1XL=meiAkdZ+{Mo{6BuqHh)gj1@ zSDKb%Y^KtxmXzKzOS5f3*>iK}9IK`k7Q1J7&oZR0e0&r8hLY2^wjv}XKztrO;yK$e zhGvYxo&0ccY-0$to$+lK2(gh{7Tg6AhP}Kv4JLZQ|1){9taop`dt)q7doND+(UsaS z<_j;3y$VYaqTh6_E(W!8ycKw77lc%!o?Z*vmHwon<^%CgwReu6#ix%y<)rmSm-m&i zLyjjg3Q$s985lR{a~ejA7$so}PthDlpT$#%Fi+wsP6;B7eROQ-$bW>##qoLE{%&&PU`}>lEzxF4IEL{MPRT668~PBvKU}&f za;xtnQyE4BuiSi1e)IA13G)f%l1;b^xGL9KH4cY3v&k||&HSEw`_j_-?(G5Qz9iag zW6J#O#uR`5)P`)SvvBCX9zG&E)SS&FHx1-uFRn!$FiJUl#tJOaUT!#Vw!z;98ObRzu!IJYgdjk8**^HUiuLVrOA<~a2jGOqy_9(oMu zr~xbko*#qAdO^)Neik?d_DMJPNhseZ&|@rAWY!~U>TB?Fspm4r%ZCGuJ*F{Tco|YJpZ@ed$AxPNaDH>eD z_0lr(@RF#;rltyVJ0Fa_^75ql2fOC&ZciAt*@olWchBoSI6ukO(w|sl_VhFtC8brw z`H0evuOFO)`OA-?cJ^1^!-Ds4SS7A7YzJVO2{Q7FM) zHe=s-K)rz02Dz6PoCWES1#&NQLp@|5P0|3BGWz?XwMQ(`3nMCmnGi9lRg?wEpus{T z0cV$1DQ_xozsB0`K2f#r#ZmUO-PO{(u~E4F@8(Udabl1ClK6%67Y_H|w;~6eb5{O9 zU7Q#mT|tr}=rzw_;yxz|8K4-c-^*2cFL-Opg&b>U9CkNJBZ4@LAyeYIAW_H;*O0+T zQj#fVBDp-JJTzp6n~=nk3?z48^EmP03#ANiSl3|fP4`7r5}2-wBqPSn{Uk&sxU)gr zzx?5Kh2&otes*hV#g6MkncZdPGa=~}%^eAqn-`UOgg15#_|>neiQ-O&p;}bQSSyXy z0Y~1r_A5u4n~!{DtRCs~k?JrY@tRi!j8+o{;@Ly&vHpifi@WA!G-n6rtvuVK ze2ZnQSvNYQeCsb;_Z`^!Cpj;wdQC&a`tTX4rOgS@`pxWp<>uVx#RenM|G->+SAdr*e>{U0V5$V!c58BfjXDMHk&*67ZutMxb5K|_S9L_VZ z0_sp6iWn$q5zsBM69bI?XzNMb#orbB1J;rY;>499|3ZKudHh0rzS(H-6m5sSAF
    *IGv`(SInDhmpl-TqajziJUSy#S-zefz3d=EXm{=ot+S$hPo<_ zTvLZgzIEr$$g=*DyroUaHrBA~iJtz4HLsnV+3bJ1aRXs!uS=n0KZj@L15Q(TUpnM4=FcKDC5_*ZT2XI(*@K92;R5_4qS`e35IxXhRYc|^h z?Dz+We*gRLP`NN&&Qr43oA!U&-{$)V$67X{f1Wq)l<#pkCd>E8ahXQGFJ=@O=p&nN zD#I*l?vdqLk|nn;-b>`Kc}aQm#E19Kxx#YSKE9UG<1lvz@jMHEAH*NKaNV(%oUZ|O z66ggfj$X)}^U~qyL}OD%dP$KI{!SO?fB0+L_jmq}?N1*|6}Mg&&)b)X&)6H#)A)M0 z3mlUX-+(C+KcofWk}OS*Iy)wQ4zVJT!63WZ{|r1tPaFHT0!J$j+`Dwf?u;#PtoNjN z_KAIS1x)MNr1mQ9)`$rD<24BQnVrYy;3)V8YOElu64;)wMUpjwAm_m~R)c=>2)i(t z+(3T_*#g#KCPah>2O0giBR!tQ6XW3Zp0zT7+-1(i5T|JsOi$dB)>E6vuCkiV_s`pM zV@pvH{#tZtwDc;oRQBe~8?6ots~X)Mp4*UEy{9j~vDVb~Qq`Sa zb$F-(V_S-K+k)BVb3n7oY2G*y)s#?9MPYQ>qBP%B+GQW1IKo}hTMZG^yIR~U3f*Cl!)V!e4 zWTHhBeWnR-OkwqYo3jQ_EU+y+xil+#@Z>_q>AC3Wjivs}o;%v(p{!&lJ$sHkx75FM>p-pd*l)aR2ey`%ZNcx7zjxih zmQwXy?)2$CuDmQC!~9Iv)v&8SS66%7#{PP97j(7nf+#GI9t7c!WhM0XqyrP3;jw8x z;IB9!6LdB8{9`y!)i}H^9UAOH&A&r4MR|9aGHl86d)xXij}+P1p3N;MDs1eqmv`Ed zvx6*Od2QcjZ!gh^=k3Dt>iIi3^)hvr|0jA`-aEE;Y-8kd=ImnFYrJC|i^hh7Gvs6L5Fm&X<=F{}hn5QSX41H}t`nqGz-`>D3RPuI(G z*{{B_=+r=F=D?{%$`0lG_?Xv{5fG5knhUZq09R*q_15l8>9R7Y90^S?jf^PEjKI6A zdRZ~XGreAh(fptFvcC2M-O0(_`#Y3h+Qff=y}0!yms)&$ETzff18JR`tE#rn$8yjz z*xy!;gr%26n#!^wFh@kstb9yU^fFHP|4Y4WA*<^>y%YxdGrjgP8>`Ekn>9NyYfhf{ zKx)V4n(A%c8R`f^(@LWv%Q8)TPmt`K2O5}2xKG$4FytZfSVn9=z;E$MFB|kgebPuE zq=j)04HGP}G3E&bF_9&5XbDe76{`pG^%!VsX0-XaLo3r`{O$AAaM+yt=*5E>*yu?e8_-ySlV=^}UV$jmL&c zONWj%;$54tZ%o)XnqJ21YeMqJ>X8yk3q$~XPR8ie%VvT3l3vD0#2(koc$gA|VJw?$ zvMJY;+uvYbOV{KsKey-?0qOObtV?+@cU}(CDsH{bt|;B?tLBT#t2ec$DbGe&Q$yJx zwlwD}YQ2L0yf)dS+F}B`{afJK08R(K&KhfFG@M?tFAB=}!1*H8!W9Na3|m33LzBZY zxwvrrvvCKmNvuy!!dv>p#8@I#dpG%GD9AblhFLgp9aclcQc%#fL3QL3+6}>;4=DfE zV9(iO=fbl>JzRoAgIr3h*^c#{_a@q2e9;C)-=_Rb13~|V{ewrJHMpH1q|IgBo#GSw zcBB0H*dJxv>1$*Q1Fz*e507#Al|Yzrn?~?GR>~oJsOJtaJvtfgT)ZDFB5Nq30Ko<7 zT0#O0Lqx$uA!Pb<_nCqSWn_g)pCgGhuC6ib*g0iDXRaRlba^Cq!KUIf)=dj?@P1cu z?g)QFPl^~me-nEXIOO<@UF!Ud7$B`)+@zXrxc)t0YIN}S&6pPimErzt*xR9y%BJ;! zLf4z<0}Ts9^jmybTtql-37y6V%6B`rf~!)p7p#nqJQ~TRw0(b9a&p)H_FG>ItJ&C< zD2H0I!e@#ZrOD7Sye%ckU@QG;otvtwwt%fblK#Sn7w4X5h3lVO!``-kOF0^uRUToo zrePGKup49l0>(~0Q0_UL8-Z97_(zyBL# zZ&9IS!K_#x~{foK@bMTr=R_du@m{eMxzLnwkMGoqpm8+8iHm= zjPF%_40Q&%K1TJew}Fdujf^S{@-`|48DZB!jwPMVX99*E-uH@ffy-@bt}RTCBXHL- zhK0atb&=SH7sT(AZQM{uRL7MPWuBoJqHiv~Hi5P+L=7moRU8t2}(`NJoEv$N0ZAz8?7J zHp}@_$48p#XN}JR1g1%^&SAk*sE*G|-W=bwy0mfB6uz#pY;|J-vlV0(RK3h93o{Dk zd^>C1-lh(&ZF{SD+s--`FYXxsSF5u`_GmgMKzzn|h9`~N6d3{nc)c%*b)aoX#oDn* zr4nY}In}={Mf6zdy+@ zjI&HB4Q6Exp6XRH zzVa0tE2XdUS~F+Q&TP$-GnAF7og~xF&yX|DuzKZLdm#z7B~cOOB*4Lk1DnqY*wwRz zZ>T|tsR$B6oC27L79#|$-j(SLf)*v@4mpTBVqLlkdN|a@fpnbt88^DStBwK^kM6kH zn){#M=jO)6DqfEQ4@RVwcQ!0b>1nEM-#6NG22mNOo!b%T6GG|Z&HyE+uB}qY%u{JS z2isdVx1|~$(FMd6B_vlQ8d;$7p)s){IiV=dsDH$e+P1l+{a{bpsT(&WYu~PK-d&r& z>cXPJzAAIpk}u3(a{By&<4dxl%6f}BP7f8;9{%R8^Y(UZP|WXnob!W_E7OHTs6>_GuS@v z#SEpVB_+hhP{jscL_MlA1XfN=EF0Eokvs&d07^B|RpWzZtTULTuPg70esN{Vp=r^6 z>}p!uh_!QHcZzh>W;-gTbnox1TGyI*)h8<5lw1~%nzr%mozjg9vV&5JqpYJ{nRR=v z4Ja@(D~SVN+FPHqXjg4)ZH_5t;U+8bJCJJmX-tzlv?^q6%|iMy%msQ_B^XtzA@?){ zBh9*t@uS8ddHHDBA`yWA7Z)>0(vnNI6USdSl^=`F5iBYwYRq7 z-PYpW)S5v4WN-E-@e^Rz$e1Qqm9UtW89^4@Y09H4e7NP0zoq+xI15y+C%YpIyLel~ z1YD{-QL*&J(MN5z@4R!7wZ5QSd4DPUzLMbhK{V29Qa=2)qoPc6yawZV5%28-N;J(l zpqkMJ`tQf_MD=}53tsFyZL_`g?nO4|Mdk7DEn(5h`;H%o4|j{}An?BqEfnKu!#MU~ zt)sB&@UZ}|5o?W=CYngDM1Yu66bz=sfH_f(@G)jIk4i;sl$W=k8SY!;2*MxD0Fxc%)%i@vjs(dJ2Q+`!5+#F|PzOjXI zsctuQg>i+kzN}RDv~ueGzN7P#CH7M#T$i%o?%wy`FYC-QdMOR;c~{CheqWr=DlukA z!W`QIc?kk6le666>tN7;pp3)xB#3>2ySqy#QE&e`8ZQ#e!~pHlBgAC*iX z))*%(!>kQ99+80ji)?jMnj{luTspdO=UJ9s7-=}`Vix7x)U(X@{1Z>GUB455tK7Xy zQKSIfJzr2}u)o)p_}Wj1%Zy@44Sj4buYQ;Aj1QBfE&zW%s?aJqxSXj^&c%Cww{aQ(5 z#e9#vsZ`2QhIK&Zs1oK{TPkqY{SZkd*2b7csR}2|pdS_tqG6bDuaU!mh&3(Q6I@Zt z2LP=`erRQRS&6kUKRqQZcm{ZcP{fMdCd4$s@}bECT5f+lQ?vYxh9oJ5pAAhmK+KMh z6SFS(;@RlhRn^M3S=zwWoi&lx`MEof)b6^rB(t%~l$LF*Or&OFfq#o{Go7QfPIzzcxnG2h({;^N)9k{qMrzkzPFd@ust8adDe?i%zqR`l? zzJiK@QqyVaiW3`86n=uaan*++KfQwHrVMlA!{;VC>T~7>OmO1dRFs#N6c@q2loS%k z=LWtdJ~wGubedX0pyNfGIGc`{HQ%((b|G^7RjNr!-b0 zVjL)NH9=S$5AAb!xubgwKy+Pe~l#wu{FJBq8RROSvMTG7#_F z3(oEc*4CV~&=XRU!$J`dSDaEDYYt5cOG-4mz|_v}KvUA8dZ7-qQa0#JexW+Z0CKiG zJ$$W(r8M@kc!lJzP*l5@a6xz^I(bmY1&uQU z=X-?7=pSP?#Ye;k2lENYqL(aMIH;{&Ud0r)Zt99XrEf7u@@R@5gL z><<_c8dj8-FRxEBh&?We^()i@+HEJ^7g-@GCxzw$mrTsUcRX-1F~Hp z*6;(}D{zCCT*rY1tx|JRy)aZYYZ9`qny_H?!>Zx5(*?Y@eI`tPvyyLU;JhSk*(>trno?3whx6U zBWp%YWZ;7h3YdK@ZcjsSMxdYGILlNpOL^rUW#A=Nuw;oCwrdz%8dk0h%hyZz;5aEQ@=cr* zKSXj>3&?RWA`mDAcIap*gc77lB+_8kL!h;imlZmpn%=;P%X}<~NkV$4f3BaAb`s)l zHHjEibBd4x2kna)5#p)_%&8T1C}2=ZC)6iZ>Y%U`BD>ZitF%*wi*}Q+<>)ICJH+6X>bO z1lo_f1ZO5DW(K*q1ZO2C;9oIz^oLvwA&_aZCqL=a?;+$0deFps43Zw}qx-a*`0F^@(}LwQ6#6^ z$mtRrPhA&Zy@@~eFFUxL<6oP(VO>K#f~qK=s$sanELF07pPXW+Su##c+azx1%wcc3 zmyXB1FvLqj1MGo&3@yl9tVac*W!8aWHq)&HrlAhdSyW-xp*GXmZ} zcfoC@yIbEZHUl9xGhF)sOb?b0TODGbsl23`;s~amnc3QsS)W-~Szef*ljVnsW?r+S zES?^u2NMat!=}hdvmfaqnnh7FeNri_7#|>C5M|Z_uo=0LwE5GK6TmYf!C9q<#@!1t zlIDz7){lgnM(V28%}GjMu)C?Tv!bw|@@8d0K_z2d4bR8btXtG#PRnIGHm`~(E-Wf< zNK~p#5r_Swl4t9#ruQFTWRGv(*OgpdSy`RjwXa=#chT|w^wVtnI(vNYs{Rf(rpO)r zt9r$E*KKF)`5m#zF^7$*1S7!|BO|- zQ)X>u&HrtoDCk35u?+Jx3nflksKnYWovE-Cm(>rOOe6JWtDE9eJGRtSH0Nhwjj&Rg zg)J3di?3bR+Y*zO$98O4mC@a^vRo-)kYWqU<<-wD8i#CMqTi$|5eOUpjf9bk}GZrk>o&vywxKj%IH$eQ&28z;Sg zjQ0K%CBq{s{p-{jfLUbn48%HS;PaY(-W&j^f^3%)93hUq<#aS4TmA=3`Prk&U!?V) z?sCvwTe)M0^3TupJ22t2vRhsPTX~c)=Q=DBumh$w5OcBWs5heK z-9om&{|lVWV4r;saq01%6!8PQ=EUs$i2-2wOp3FuzPhEfa`%nl)z`L^*_gRzWmVm1 zvn6H0T^*~G-E3&qiYxDK`sbcsKGs{Y^O@CkTia6*Ho5TMJx}i8`Li!$?D>!h{~vYl z9avS7#gE^a``$}PLVE8n?WOl#UwTM`1V{ry0tpZx1rj>amEKDzim0nnEGXg{bk%k3 zWnI^GS6#dAT2@_Mbyt*k^ZlH;_l1P8e)sqN?}rj@?#w+ib7tnunN$C-eaG4Qzw|xm z7yGX9#yF`c77@1$&E7vJC4c4lr8AEA72F?D*pga}7;wR5i)-eg?|shg`!38;P1Y9f zoto4{CTlxOqlL*D?lsGSwFCNm)wU6GQfJDqI>8p45ob&8`$TI*_)!zSM*-;HwF*blp!NEog0XAkBc>vg&zrm&(SGNPVIhpg1V>C zT1*AP#6{wh;XTVFPehhXz>kV#zO-utDm@uPfQuGyx`lavmerX77pxMBiSmS zDo-0W>+i>%Fh(lG$hzTOd`!BZ<*9Kv=LG`~ssnjAqR-kO&$X>VZ`&8)=M!SDpI`^+ zl0#pZ8+UPa>33&3Pq^Rc40FAituMo>vzzPB91uZfqJ!gH$yvf`bR|a^ajW#KG6e;M zI_W1)^qL6NcKt66Xmq&fNK{ zQzy3^+j8vi!M%HSZ0p(Fvw8gut5yyyZR&37?wUV$PV3B~#-hflbv4x$WwC{^g?Tv{ z$nfnM;~8TLHwOFr0*92mB9fMy^+Ie7`s6YGjrHzl4OxZT^Z)SG|5E2VkpC0_|E0v* zjKDs7?{GiAa4$RdUSK-C$_!jWuYB=plKMuggg5rei{oBdCXWF{wJbG(*Fsm`3(Tmw z+MsWkw|$!WW~4n&d);?Yhym)KTpHyb=I`R-ALg$7W89kw*S@h_zV?msNpxwFzkgC` zv^#QZAOxAa-gjJ`{{fDKfY!CjT$?@mXR*~LK-1jH?Tn*UVAV{HZl!#Ae8F~){n+i|Uvy5;6x6zxzWfS}>AZoFZb#?Zu+sd*X@Ph|V zWHriNKMzb)F0dB)X3h#rl((;Z$CW2bSwxJ>p~7e7HkZRi&p_OCFKgG`?#SwuQ;Lhj z+BxMp^n=~!e5~a8D|=jyl|Iiu;jFAwdE?5*TzRyd!32clP`4|{5<)o+$(PpIr25h# zmWC^D8-81Ig$4g3jB+j_wDTjwZ{q>q+=*{Ku-f`NN06<*_+l2maIxC_k9>f3{(oY# z;EHpW>`8you0qJre!;E+n)Wd^3uG5J+Gb%dydg)~nI1ei#FFTh)!I}J-E1{Cl|u(N zY)~e{V8Lo}DqCa9F;qN0VBkvL4Pegb$x#5ZYy85#L>U{&E) zrPn!-djPtt)5LIo;I=sK#6mb}73Y(j80PYRa19jiH9ZJevukP~!DIzS`zh zVPPw0*7Q|`@>y(I>#+d{)Xce-AN6l9FD|b?@Y1Tud%Mk33oZXK*Fkg!*#Hyq1 zU`>!|0{EA~+ejL{z(~j!1Q!?~J0`O<^4KW1L|x)<4ym~UkZ2KqR5(fc71x0y9}Si#;D}rxiMXdsluYI@n6iRb2hTv(kXqD*kxo&+w5S`<6~e#eCe^r?y)I(DAXC-43|sOm54pUOqWW zftfJTkI9K2f}HRuU+l1m3>@U4cP9_U#cZ zUj7kPRREY;x_UHdYFF?o9i)Q6Mw&Dxriw45QSykdfHP90v737Yv?APDL^jK_lGV ztVkFYXhgNErUcZg8=Udn&_fRmA)EO(H?v3oq_}YJkNH7Mx2_8Y(}T)y`AwDr3tTDL zFw$Y^))^$=06IliN9=#h223_Vd|_bJPB%BCG{p>%PQx2gGBFvhY9CyMB%KUPG{ZoT zP?rp~1BPvvUVH7*zy7s~&HYfRWS9TJE^h`q@Y})Drw1(uH?a;S&$1okk3;)+Vf>C{ z-wC1*VF5THh>k&raAG0)2I&Jew_4To=c;uRblKJcA71!~a*4qJA@FtOQP%wtjTX^; zEUT?UMO&F@>jBL7FSSKx&jQWYZOcvg7(RB>5ZX}IU;aS(HCy}zc^M+2t#C8M6k~~F z?eE6gKTZ2Xir3aY_7dLTiTAL(#-8}6_WoP3CvX(#jsp*ZUJ?nxjgK(EnyEjku`4`o z)v33VGor$DPLLiWhV?_1`q(4N?x7($i0?o8(`S6EMOArX?Bu_7Gsb>>_^Pq$FTyvm zwd}I;xu@M0^}^IP`igI328*DBcB) z!rR4LRm7;gg+`HOlQtkD|8UWreOZa^``UPRZGsyM%x^0mQY??~0lAP*J^K2_jW6!1 zJebpUu(9>%q8x6SV@>MBqygn`y0sXqQ9{fQ&}LpvT|{4SNXWvIf%dad;~Im50*OF- zdj%8ktwx4$)FZGVg-aE*nW&4AzhXNJiC>s=NLtmLyu_@U1a}sa-MPCJhQnvbK(Kl+{ta}la@`1Q39-v)m&OI{1IY+JR_yyP7eFBtmI&bx*+05v}1UZ zYa#mrgw6ekO>?Yoj1L6-0!?~|?5&P&bX6oTdC2uir7DsQjHqGZ4hN$bB;BD@ywJ{S z+E?9_`U3@t-MLF1-cXv*xVDx>WSZO}Yx^r*f}Lly$4u$3sOX;(!>Y7clR>&u?U2EB|=&jFUx61{;-6JI`;f(dlMfIl-oOK6F!U^^NeP zIlAlHCWncfZFs4q_?ZE=sC0EpO8ShI#h|1!A-CU&+?pw{Z^8I8l7g-?ellSoi9Gl| z3eynl6BRXn{HpJ#2gWbNW+}Izvo=@uUffuoJaf~O z$oy!}=-QOC-znm0!e-{6*sEH(YE7!fGq}qAftR9iM=Coih@eJq;g}36Pt+Yh z!5673Fm*kav3y1Ygck69?4!l zF)WO;5%~C2;3;3l2ago*d+>fa;Yn)MXfC{k(7!Ci&q3@b-1N~uQY4FbLkyV?trXX$ z1zJ%r8;$JNsRRqB4juA1>u~xY{uKUYWt3ZT=>VX$x^V^CDm zodud^SRP4wxdSnh#ZuAiVZz5&LkQpN)oV68>2$gPT>#~!rU4=x4;^2a^YOu!_+5t& zvyI~eE+H1#W9*4v2)e|j0~k{*a7}m1BW611A$qAmEA4S%8A4tuXCXld)slbtl&Q+)q$oOn8L z`&b$}7_Wh+6uzIZ^Ai3-MEr@x1o4lFX2@t2of?xG9O&ci;pPDEA{Iq{uX+)x2T@8> zkYrwnO<-`=Rap?vh%ww7C0lsWqbI&O0a z4f2$m`f9h&%l+=}+E~BT-3WbA1njD&o9icHl@b4r+|zQ17%R+F3|M>QYbfgsGI)6{ zppU9RvJN-W1YS7SlpL8H6yW3S=3+NNieM3=h6|ZLhO15%{4@eFYm|jSmWAOSjh8Du z_pdJ6u>KHB&vBYEuz$*;TNk8QTI7g|uF{U3iIv{P&3$u|r7lQurswX*ugj_iW?wMZ-NEx$-m?6(AZ|inp{Rc{s&@jWG82cQi!$jg|)BeM8CT`+%#6-II2wA{bu2V32bbUff>^W-5#(dB~X1WNFnut(0ga*!VqsR&(?RpcS~O^Tc2t|u*#CR!UU4NyCBf5YB+ zS$h$ZuHF;ZxShvW~0D8}Q*|$T{b<3**QUe@q z{Q`Uqg~f`~5D>bUAG-XXdW1%|wL3^Yzuk@eJG5Qo+ zzp^?o4Sn(t@U&XmBiO z<6)Giihkn8DQJg&9PJRk@`ed$qe|^3^rNDmjnoM)wcuXT2)o!2+|!HA=0NP$0Cklk z+^dcYXFdsj{$z_xrq)*b>ab7>%McnL7VqQb>VoiQAuPmJXni${PLnvLuEx#726q#- z)^t$u{7uhqFPpscH@)i~TUQ{Ln5N&2yC*O2oZp+jI-37qM1HjL0-DL3j4FW%6 zY=(b<9&ac7AP3CPEKZw)IBgEZH~ROnw(yOMLF$h5Rp-E0odcCVQ|xp>pD~XU#XOSz zv2`9*`b_yJ1bvpezaN`lLd3AONkjPyT0gEJ{*P+I+^6+J#MIKii#ngH{jl>!KNvsn zO%<4Q2=i1A3J@mcnzJAhWMR0_gBDpMXdp|cjw53v=&kA>1rlI&?u!U>j|8u&%7D|1 zl)&mbF>c|#lO|VM2INkrbS^%-EPvAG3kw_1Y^fWHuIwr(Us4-=_pN&&Qd+LK8_d18 zcFa53la;*SRBzVYs+g#Xj+~qK45FXgm1VjL(5Eoi{@IIuVvC}qRp%20E3NXxFmHs_ zwXVn7T~I77N{cVq8W=U!d88Ur&FO?}TMW*dA{b7wslOCewVT^p8oc8e>YF{MdxP7d`d2s|zx0_z=i(Vbiweiho zOLzYl7}i(;HW2M!wYyocTi@BgN~w-;^h1H3BHCeBXL=7*w9nolboqdEnmO^e!Q zF|~>L)Y>cp?*T4^+N_eCP4eO4iBbXh+~dQfm_zT_`2y=02T&I>Na{zuTDM@hL)0xn zUG?1WpvqV$jY^fC@)IDwr0DZ;a!JMe9>BPhU}$oST#mooHig9bU)sL?X14gxxMIEWCR=>* zZsp!T!*j{_mU8bN_MsBQZdN+jhlA`XrI+njkdp%%0mS0OxE;a$C7R=e5*z-FMD$5T zfWvvFDz|cSk|YYT>*|cU6O9PQ1JxU@x<;JIB3m33?Ib@X@u|FGNbz2#MzvqY5|r0! zmr_LgrL}T5FaBvt(egXm+7Z*<63q+ZYvyHUEv!$XxuJZr{^HI{{4kel(6`;_TQD>l z^Hl3Lf0`DA%Y+*vS%e^7JfvPTH4O@7Nr6lSlP4nK{g+xuUu-lo$rxvh4GZ!1g6)%o z{RAnP1<}ROI+`3B8pYj2HaXl85k)l=QgrM1*sHDk<|HT2+1I*sC@Cs0+LQ6%fD3++ zoM+8mU;f3?^cuuAPOM2UUUB>E*{Ax=81&y6OK4b8G2@vTGoEZ){@}{oL5#h2UPk6Z zq@ci9JBL5h9YV~87|BeYM9|$yd9hH|ghG7}S0WtFOJTmxVRndHubL)>Or$wiQ)$7% zH_8-h@(OnooNqmgaTu&JZ!Kq|D)IFsiMOdUqH1YX>NMjJv-d{g ziev=7mo%HYBseNcU(jx>RNi zf38EAY{cY;-VoWP$+8mWcF>v8Tw+=!nsLE>;CiIfSpzI*rYFS1Tr9#EW<&mAxU!3o z@gnA@c!CK(h5MvDfe&;--Z;UH-}8o-AkK z0Svnnqu%<;&T_t!&U%bs%J9d!8?eVy$OAn=jdu&j1uRxdgagGCwj7KBDQq+t7pw>^ zYNIjC7;f?kAwDad?API0cy&o)07$HfdACNo#e+6pq#ERZjYtbg2}Sl_W8g!+F`TD0 zE-Sien}IEwdoMq{x^H0h`-Z=Dob1kOpD}OR8>Xa~n#D!6chuINs_VI{FH2s!v8u9` z9ciqZJogCQ-lp}2`LCN^gSC1A`GJUUgwLd8Hs^UTodg~qa=_#y(%F+=J?^rQ7N}We z#dTI532&Q`jt`@QgD__zpck^cs1aJhaans$v*qdK0Xt;Xy@WjDpg)36B855Mappu= zRe!DWC37Em_=chtefbUPK7pnuynGzwh|>04KHm#^&;G>77x=298#m>)W1i9$oS4`D zt0ecLrp0;N3c4eFJPJz-+_vP-DGj&WoiM+1W>`Vl$>|qpuDJ9E<$#D!90gtovxTUM z2ql@A0GXLyS1$64z`zVsC}GaDF?v(By|h$_=OQsF&Pdnbz$s??zVnat7YNxaxiK$;vGp#?= zDY>XFzTGuCI%1-mV`56e#M$*NOqn)jP)u^i{<>4lS*uD(gGi`@Ed~j+HG>K1??%Ec zQ{?Y)HAs0%E{zaQT-}0@z=H627?IADEJ8xvMzZ$gBe1KQ=XfjyiZJoHFS5|7+dD(N zQp=*TLbI5yi@#e)lF^wl5BCf10Yq^6i&k$&a68Lqk0>8KJ#Vn~#HYvj`JZR|rI@@y zT@EyiqAq;j5t=(DC19L4VxPrGz3MolAuOT;1AM=1fZAQ`FA^8hXyJ26TTMLDB_Z9h#hD=g8^9wD1P4bF=7WvQ(jYiB>%I_rt{wU2Em`6kUc6Dqa2+|_s9K?KL7s9lP#v`Ot419p# zkjU5N`jy1Wh30%FR8WC77@0lBLn2H~3x(MdQGJCHc+BY!Qp)Lv~&vUIDTG zPLR~OKL|YVgu3p6jl1<)Xk>)A{%_NVAz_W~!M%GK^wx27?{JudIfZ*0Ca;|y7dIVY76xS=;B~>y-35NxwVUttn0?nro0(zrhj-78joo4ltz3Vm zRrzuD*$tKamTfH;TVh*g%!und-J2oCa0+9X0vUY_jUfPBav<`$U<^15a8~0?Q&UX_ z!T0&aX;pi&-v2Y-JsH!SW>pU_bacuL4RxRKL#|Q15xw+?X zpRm`Dfa)5)USRNuZ3MFiSX~_6x57SL{Q5lp^ zE34fiGQ-j)BP=jCf*p*OdBNg+^>8On&_Tv=^h#meU;l@WhH_AL`bF6Mfte zH38{?Yfs!~i?GT^EEnTz(XE);#YK}(*P80;>!W(^UXsNhc!K)07(96|)@r_lTuA}K zmP*nisEGb*5Glz95gxe>7&I*!yU;vY1w~9kOp&Cx*vJS^cV{PX+K4MM5^0sNNi2;u z7F1dU*ie|m=HoRO8EdLMR6|yAzHIUh4RJ{=8|zB?>f+c?!_M4x9DrHx{Wx&H~b~5&|p-kFou7`-by!|7=h9EnL&kN5HN(i z|501r2#j8EUTGQ(5{HTP1Q?GPphHx326C@L@{n6I6eO)c^ARCD(|YJ`LL-_;lN*^N!rS00Ec2;s5bCyo!gsHH{D=R;fcDNB_B~2 zbEV>&q;Vto-e*HP3o&o(Dz03w;%c9*aRdf#%WSm< zWA&IZLN2e3aVe}9#hhi1hEY8NWB2g)Y?20J(r6eqb|Wx$e?u0!n0KZI*^W(8|P2+h`>`xU&@9>Xee-aGq{-l0fFp#~P3ZwV(_)q$B;v99T?gg#Ty)&y;ScZ^#DF99FZ4Sj(1Z>`Q(po6Mh_KG&Y z_hB89twMyP!kMQ#Ic^=kggO+5IfCLaQ*ZPJQODYC8tX#X%C`$UK%uW78Z`VPVFdd4 zAGNktE4RX*fX-UdSI~NXW%xf@o&RWcRK3SvQAdT-p?jIlSL?9(Rydf$dIOyqDx418 z(6}>$;Cy8(Tj5|$US>T62Xojn3eMZ&%pf>elYbv`W?-*<2@3$|7S+DUeZ$|dSsIL4 zDvaT;L|^F4P+|1FJNC?=emr68GXkR*k_ysoP(Q4?4btP>E6xlRM(=my&kTVV+maDD zJ;VQDRT`YCQRAr>XNC%==acbkTg;QqEESGelRH_TmOn>fs^m^X2D z04}Y`mFmesv*$vKmrf4xftW=>qe!>(tk6Z2(OiRn+9G%sI+KK28gN&j&V52JL}x$Z znXe`83Gj$}Lb(bf6#4}fM%nOD!8;KQEAOPj_z-ne7-jneU11ts(O`g9sxUwYpBu-6 z2pF`U1Pql{Udw~1eF3f1;Iv8y1g)gLSZSpS$9V(}(aIooL_st~v`^-Oraw#iG=d{& z`s?ET3ha&hbZ1Atou_+g+}_xUZ;QlU&C$Mvz8Wwe!uuehLqR+-0dv22PxAXBn@gB$ z)W;lm=>CpYRr+2=9inehC&;h_b?~jI^9X#VR2pH?>Hv;@vzW^YZ7v7K@t=UBSM^HZ zG$}Uya+Qx(zoj`;zbzZyHje*Qzoq!x_?GzJ9iyUiqmL>KnnM8t+KvJer?C07${_3eiluv}_SI!g(2 zNLMDXyzEPz6CXANpr6j>i3sBH-NPrjX+0G_{2 z-*+V>3{@x0@0b-fsq9b#lpMpu>{Yb?k--zV%F*2~Nl!wRCEiccImx#f0$fdU_AqXX zxFu(k?Sm+b)7i+o44x><8EzA0Ig~pbe>fC}ugVLg_t76O$=wWnD}o_NqsVZTCwX27&K0>~+f_N6lg0!4Vx?HGPNgz%>QUzo|nDdeXh`W}`-a$I@=1Zk2V1V}0L)eJ4QK#NH!0Pe1ffW-2#TbK z@L8`ffXf-AdcsgYkKh-w>QUjB?Q8>LqR4QY8qpep)XAu8P`ZYcezu$b4zWR{3xC_# zsX^IJw0i6cST35wJTlb+{|lfxT`z~MAAk%602wY=-o`rOXQJ(BuZ5`k)Btt$)>Kp86Pu{H3a3)$jxpF3Tn*Gn~@(B zl!xD%@mp5j%={qb11hEW!FesYxij;FSCz=lCF|^cqXGjWz3uINq5=XVee9J}c+%cP z;$OV^z}`19&>v6sKI$8mkl9%i9~~MRjrgURv6=H~;-W%BqvD`Fm(Soggf*Rq*PYez z@ztG~mV#+~#6zmLgg`66Z%ImO{~rAES$MA#ULKE$LNHy2uMWEznM8{mA#cPno( z({3JtHN3@*-KfDis=mcCIWUjliDD4u8Py!CXxIg&@oMA)0#q8l6@q>w03|Hy+-I3wqB}*YOPL=yv{kb*fNi3{tU<#tlzq7D8 zH_7sQIauIU*p252UI4?uI1elDDC^a;S6Q!~V^SAr>T>C!DCqUlA5)Uj~=@GqQvD=}x3Tsc{?HP{<$?fbBrbj%JKaeI5A z;iqXrG$j#FTpThSS{^~p{LJb9<41bEI6j1(0O%m%o}{P7Mn^@uxEo!HSRTrJwP!QT|o7TLh zwsc6TUDK3q+dOps%JI@TGg8Dw7RHsz=PYYubHiQibX#0J!)jJe<(unw%+0X8q(7fI zcY8fEC_gC&lIs^_W-givD;MldX{Yj)?n47^b%-^H6GA@B5_marLy23|+aNE;DiW8w zEn+!=lB~y>k%je?AWbpX7?EWqgc)qL@WM=o;PM7LEGdJ&-QH@g)sC3{HZ!2)E1@IS zilc=1xY(HJaFLE89N8$uqOv-D2=vg3O2c1r2^mpA*&XATIvE*XO%`K)_3RDZ1jZB#q6e6kNgI&p)CJZZFNOp-$iD-*6JYRjnWNA5njvsP9U5F#ZKm9lB7H zND1HN4PVx6)6d6u2ZjUqDfK&BwVi2_4(+&z@BTsGaapL&sJ-cEZ_=AOn%NZS0Fy|G9AzGZ~#`B>&WI7l;E0l?(s68GUKjX z`=X9bm9<;TodXK0W@PVub!%ba+KU5AFRU#rSb6V;nm%N3pVU`9c}ZocA+lnTtW=kF zonKcT>^C^k$K8JIJIZShrS^7`A;g0!yJGf z-#r|o3&;Ah0Uu=`J__!|;$ox=AF_NuB(Hlz|J6@!1~7O`N>RSk9TjWQaKTna-3gQr zDQyBHZ90>iERV@sem=q5ET?onSDph$Uuda3x|hGq|G4j{1soZ{I0IhkOF0C58{KIH zZwRWcv4$?r;!cC@C4YJ4H*&GCxPu=u_U-|+Yll9<{0BG{j?d(8ZRFmbK5Wl#EFbOu zVTk3hx~?wWY&gCS97hXj(g(WZ^1C?Oi=o-H`*mYQUc8S^zDkNsW9$@ghKd;)A~;8VR=|s*~0SF#?n+bx3toRH2e~_ z);T;cE-*bV+}}l(5yLG$EigVW-1*8uypIn|iwpOo_kQ7V>49;0&nwF}cjU&FHAF`@ zl*Q(DY%Y&38~dUxv9UPPKRz=f$tl1oDI+s3z*O9nl+;vg3W&?hNOTr2fYi?rjaN%c9A0Oq`72mjSa(G#|w@X|=%gpAxFKWJK3tRMl z4L8k9a+t73Z&=dy6U@kI?eAvpx_o(9G6L7O7mJgPwDu9-KP4S#9eXav!=?ddGGy3t zy)x{S!Nk?Yrku2t;DE%W%&_9s33iFAi^4OK5(9%$Q*%vt;r@TEA$OJ3GJAJFXD1(5 z``VIo#gpw_eVm;A-H~{#wq&@tmZ8+&2}aQNlS|H()Y`eB)DNY#FhIvTl`bL=dLi!p zh6@gaJ7%;&n9MXI5&sM?8$=_sG3p{LS7z20DgR`1HYniDDr=HHQC{A_9%9{(q}+H) z8oupNO8afYL`xo(Cg>*WwmQ$3LICrO8Po$DcbnvDStqE^`NuS(WmzYv34QYvZaZnZ zWB4Xaa+WTQeB*0btA6vU^_#WoH<*V#*eeCtD|$pSvAyVEi>OcNJB4LoMrN{^fUUy= zce6uE?{1}=|4aGa#YOpvIXJt*PRnG8;(y_GDJhnJTmF**+Xd{*_~8Z~Dg6^N6~hHP zJ@7C}PQxQz!ZO0U!o$y>iJsXqHMk;webppHeVZxS>9*<&=z+f!4J%-?REB8Z^^g+J zhGEHkX_3?`^-F7{^@yjr6~1eGrGpakR36y3XV;ExH*MLpVcptQ155h47k4e_>}YSB zHM42zl-i2&lEU1atkj4gAIAyY6N3`W0*EOrY17lZ$nZ1*W~KNETXvIJ=^(HO-0g|` zKP6mE3l&xK=n_lu32^zqzw{jH5l%mm?86fV#^mROUqvQX{OdOQnV`WbRS&*W#QDO% zl?9X4!|I(fJ z^BZRu%f)B&l+pk{zksr^W5vfT=Z_Yv|IAM@1{bC%b@}3t{8gU#!^6{yiqiAx$BLL3 zFO%(r5RaHh<+T+NF)X=O}x4g?gmOz%Kpeb9jyAg5_R*$>88( z?->{76<#{eoY_7phP}k2yu*WCy#4F~LOpC>eDTG_@c4pZYWoSsdG?9 zmO08if08M%u(K>9(VXg=l3Us=wu;KIzJ z?8GP<_6l!Em6rIg3q&-N~6PPvVtNqJS->22jv#{9;N$nw&16BH?&x#&KT|7o}k z*$VMl5uPx^#nKHm*&s7Zh9 zZTKu+bg>!TwwKr{2m+9y&Xg0A-#z#2vuBy>WB+D(W^YrfzhTWTuZSccru*d5C1zN= zS??9<=HqNLv!TkE5acT73cBx%@m)3?MjNm|xQN_kqsFJloXeM=IeYeL7IIYCyX%GL zb)TF($qY?Qrf-=&`uF{)Z{e^=v`WK{9Lf_0S?Duo&OR%LJoo%={TIql`1%3GLfr(s z!1&)(HYX=AJ<7`~Dm^gj_vjYZ&t=^n{*58$D$N@$vA^samE^rB)Ne@d6x%$d$YW~G z!n~FA9ft%#((Tdh1}|kNg_}d{U_?nPPlp)Ia9Dyh8zlcD8eClJgh2#w~ZzMDjTU0oE>O$f2qi$hSILTzNmrbF6 zV7H`n&1onI3&s^CXL!7y*awBt#DNRY8l;Fj7gF2fNQj3v05$9~r@Hepkx`jpr z`8pyKAZb${{Ihhj9`2uz(^05t+O1GALful0pC-u^6@nb-HrTUF<=~K>L`3O8qE6iX zL3cdBa^T*gOLwSWcSq|oxE3&0vTusxQ9fmx%-Y|V-btq%O70ae=*zLtuwH@e4 zX*%+3Z|9Qdjx?svJJh;-Lvioks(F+4^p&zztI;av_t(JxRN#Li{Hw^?lpF^TCsf5Z z1;qir9UUdf(a+J>#R=6Mj0P3gfwC8DVr^u~j0ql6HvO6{TJ_4|>5MfU`@@<$@0_`J zZW?1rvv^S5XXcK|_Cek5W6FaxJ|=w% z*m;0GK{A>HFPcGKpI)JAW~ z8Om>1@s$@?j`ECd*KJoWo;oF0srWrI{Ehr~^wCSAc&V7MrNAzT4dSMeV@D~gMm}3- z9m$GEGEZ44V}>00IOiox4ozu1+CRzm@yL>Ec4N(h%e z8EIIp@6eKNTgx@ZKbuYkn7X&&X7Vn)J2n=@a}iMJ^%LRkIw(d zn|RvK{qhr*^}PSeWC8mr^vMZN6G$Io1JEGjq@t3VF;p4{(<}0 z4~Fyd;wy)M#e;G;ICrse&nze3a zt7Lhr9$LBLq16S9<*$Bd#mbAT^4PCgP+9-9X-mt47z-|6I&FG?X&~caJulzf+Iq{& z-NoH6pPb!#%PT#+{J^rxs^$C3O3U}JsH$3ipq$nams*F@b@S0bUn!BI!wAg?GKh1S zRbIENQCe3K^(!1qHBJdD=^fYKP8N_^pZ5L@%D?l>tDo2cWpCM*$5-R23^oE0Q*LN# zTsy_Yn5piD#-_DX!qMx>oonVr+|m2IW6SYZ`iuKtIWeQ<`0odJ?ZKs`W&H=MOKT1e zl$9+#REvINmm+@EZV|m%J7x z6RO*iBU`GIgHj8N%|2xZR#r!rv~+YOHJsbgVt9;aG%QSyoHaR(MTezF2Y5Q$xTMst zY{;5bo?>*4X}+l?qc+*o*;JSmk{TJ{;bd^ln7(Ry&aASeAjjzD9c_72Q#>5Q%@__7 z_Um21Ka{-KwrVYu|z|IAI>8c0&FA|S&}7tMJ2%2P9Do?21H7}6$&7thXt8)rCNS9V|de)gdS z>FM(hx5*AyzR#Iu4hb>O%8?z=ZUffMX0&T7`I)_me2FBy45U-*Iuw&=Q57&j)j7pK zfF-@4nD0{xpJ(Zd7RpUO_v3Scg9N~O6u&q~!R7!vc(?)>hJsd>5@p13=}JmPjrho+ z_6!U$WVZ6k!FxWx^|9aH`q{aoj~r)H za5aFxQQ*Pf>_Z7qu0aHV6Cx;>A*d!0F^`r1NijdFl>dpB@JSY1L>Rn{e<}Jp1Xx9Y zHGy~%sB^)TV!0!XI`*l|+o=x493l1re)iO7qUdRKczdy1`5jkQ@ST=*@_aTpxK>_y zY!z*ndff-|aT^&r%5d=a{;t>X_Yg}%jgTPjYgaEZHeT}a=&Hp3*{Qd_r|bU|>ddLSk`oqRU#HXON56L_>Xb3DPM#%aBYn9G((? zRrbK02J%LdiQ<5_NefTmuio+(Hpi7WXKh$UeJs+wFP}2(fIJ7bpBFvduj!+vtuv+A zgvzI4C-;_=_DzmG>KdLESyRqtAN$oj^reRSQj_2v6XaTw`1Z3v723}n{y{#3`)dN) z4|F2glW?mg-N>kWDdKoujnX3UVIt87m#39g7Zqn!vRlY^#=N*Tro8Y-!qh%<)}pB? zC)wn}l4{miF^#>Hof4Ow7@Ja`6%>#)EhDqVCwfn2Lw1l~R#RSlPHsv;DvdD|e9&p& z;+J&jxTssX&g<&XQy}TeTeRpFWxIi`x=q>gz6*=lbmq)FZcsd#5u6LgY{r;(p&i7T zyx_uU%)|xRkR%}xUf-&53;C9b`!R`ra5S>%$?QGl4o~;WxPs2I@UTg}m6;3blI0VI z%ABy25a%fszL7!R4s0_!u;r|+M`&?dZu*?cn82KA=_!dGrqrNSOi;0^)}%j=xlep!^~L%JDNHEFvs2K3do_h>*8dBqEs| z!UI_SvScB&F?gu{=*ZDc3OFGrlh-hFMnQG_JPOm(3yadz&Ad3L$=A2NIBPmYU-(hn?(5r>lU|=006sujVj5mL#O7B_?EK5H8^d1D(KwatP>!X3Ig8L4MG(nctxK+{^4WomoDO^w%=>S}0`s z!M?7xpf0pGY(i~D32W$_gcmE32Qe7_(X;QYUGJZe9~zQR#xeOJq4^2^(^+y@Xd+7r z4NEpGedI4;`LRAevH4+PxiQ|}F}Y!($;qJ+$;nv%Kj=2ezlOeA4;vEOixVe+W2d#5 z;(;I%kYIZmY#`OTzwPuRQ!Y(NiK|GF*XT~N2oL3r9XYcC<*D;-0*nFOTk=zeKY&go z07ioG8akn^X*Cxch#9GhMub7>Y4TIiHQmLI$Wo2Hl9B*G=!QscQ8+F&?mUU_R>WH#|29oY(PlUh&85cQ=s`XQOzjs=q{3r zDO3j_;Si`o_Nr#QP0wSptEOb|3#8a_gWr&1;TF2~x3zqO^WtTkB~>^}D254Ip^YSq z>;+^`L@7B01C9`SKDc3v;3Wn!gQLr+#@1a;!ojvY!d{$q%j(L?RVSw@Uo+RFnWfRu zr8AT8{IF69hAw`__L;M{Hbx`yhF5Y;M*5UAe;O)UJ%fHw>{|yq)9lDzh|V*KX->)% za9sE&6Tt&-sfKB#dyfbl6Urx^8yXrDS|0NC(XrP52>ojz_{9Wij(K8;(QzUc7D7qj z*i`LJ{3#$e@J%!U}}=bBTv6v*f+P)q9HBgHlQ6lvtYueQvX?LP7_*eg zI`E3fg>aLwNxmVGtJb?5Y75xzlH37u6_l^g?2sNDUJ2bV`G2e=&Bp&$$I6ph+mR1{ z_kn87H2i_8A39FWjkS{Lw*C~oHJ4mTVt(!)ru6gJY`h5A46;PjuosZFDmMgP$J*WBv#X+EyC~20y=H3=9L}NQr*h$VZ01 zmNrox`TQnpogS=l$ktG2xr+DbG1mD)2QTDF0v`}!!q=i~xEnYUw$;L2iS$rv9l{CK zfqi~6;RN1h8csyHz=zdq>P2+8LQUai16X0wVxil-)aa{ix-HD=MeH9)sv*!dNA4L!B9Q}koioU!Xi-IIStxwio{UiE zMU)#NtmUi)G0jBz0AUMqchHypI5Yggjg^=SgJ7EI1&R$tujGKUNr%W^h%vkr{5&`e zc@Bw(uG-s8;*co^2H<0V7w_pOUs)02>D*R(d z%GEtdI9K=dz-NSWe6QhL-P43~bx*f^LO4e`;e3Q9{4i2JL*3Kbs(_ptb3$@zqf}td zMcNc7(Qq}c#2nbz8f;+GhqKgHY6sWAVV@6?brr;x!YF)_$baF5sc>x}75`8)a z{EAsI5*UJ`(#lI(9mF~e9_1NqEjPgDS-?PCTK^^$LK8uNoEq~+a%!WLWlnd-oVh?3 zgL#vP-;-E7g(;Jfb49QlI-OuQCg~vz7Zaw=m{op#y*&iZenhCPd@*j$ltWkL+~cQ= zB;VFC=-(O{!wi*XUnlXW=hm=$uqzH2(APD)nwcwb#kOb$_lNm64grHTpB+o%giKbn0rNHDTb7Ka zv7%h86H(5Z`bVu2^kIimLo!|T0p;*ZyaCQ?wEooZh_ zw~>1g(%aH1x;v5X37$}XkSl7%cqw5OSZk4mJJh7O`y_;Wn8IU(A{R1Vn1zi$bcNh| ztl*c00Ar)tlRQnWk-PK@a$;G0(b zRiBX|8d@Fond55zkoGJi^7zZzvrh74?%K0nn#MAcLz~5l3u3og+i`Tt# zdIx%gYkGU=7eJpcEkh65(Uw%-Ie*#Wc07#kZT5eGlsz&!N$pJbDA3u|$^Wen4Pu=A z7(expa25}&(SKQp&XNW>=~X<^^8o&vhyE@TBU^y)dhiqs8Srx8Iv#r>N|G8nm-ct{ z_5{P~DKRlCGc8A8Ehl(jU|##Of!+mOJp;j!%ah_$Pk5zS${=<8Da+kp{w3k)y9yI%Bu?0TTdx;iVtUH!rB!2?U%J371Dmo5tKou^GU zs*Ro(4eMiH#$#FaqA{&7er_+Gi?JGMRrUiS$O4#G>Qz7!1*sWUTd6 z?2vSvHJR8gh@1-_f;>cOE0D~XlOhba1Vb&ux~ah6D-nUF8kC?GQB|hE^R^y{n1(1K z4e$_df?;C|j0}q?OWYP~0`}AYLmyBHaet;C0|vHcDSgUrVq)M8YjwHi6kOd&wdxaJreuU_&kq zgRgLAE)4FK%#FFjozxRvpx(>}X^;JwKV0ksr5~lsEQkd&BMV`nER2P-2xelDEQ&=V zDP$~*WAV~Y(qC8tgFb*IL*bbUL(p_&cFts3EE`S*xhzlmNctGc#sX#rYg5FESqaQ* z%2+w8V3SxSLy9-)yz~I8VYO^Bo5Jc?J)6p=vFV73|1(b3Po%%GM%Dz+#1=M#&1AD! zE1S*QSUa1;=CTgf$>y>7YysnebV2hPuUXbF18fuD+kyzwwxiw z4O_)lvo%OKc>`O=*0T+4BiqC_OK(aaN`HmS>Rssr+ymcdTiA{4CbpGrW82vdwv+9G z?HwFz**>^62gyMz6T-O27^ceB&% z3_HutNw>0l*u5}FydSaQ9$*i$3ov!R$R36j$|G!uU1E>2$JlS!Sy&f<484 z$DU@-uxHtG?0NPAdy&1wUS_Yb-?LZQAJ}W`kL-2!C-w&WGy4mBlfA{>W`AYxuy@&e z?0xnD`;dLaK4zb=zp=lwPuXYebM^)M2m6wJ#lB|$WZ$rF*}vF#?0fbD`#1X!`;lE{ zKe3|u#Dlq!hwxAy#>068H}Oaw#iMx)kL7VZo+t1`p2U-R3Qy%}Je_CoOrFKF zc@EEo`5jEtxS1F7B3=w_c_}aB<-CGV;+0UqSMwTP%O~?GypGrNseBrr&Kr0m?2wvy z3!lMf@>#r<&*p8sozLNOc?a+0^Z0zefOqkQ&_XWe-MokQ@;<(VFXjDwfG^|A`3k<0 zui~ru8om}`M>5AcKh5I@Y1 z@Iii*ALGaQ34Sw2XnTGuKgDn3xAQyrulSw(E`B#Z&Cl?&{2afB-^=gg_w)1o0sbJr zz#rll`NRCz{1HCHFY!nDWBfP#asC8k_LhBQU)fLgmjmQLIY81v=J1+rN#l#BjP zV`u*5NL9u0Oy4Y%PI|g$^zef}_$P2uNmUkqGE1eWXPVA1-C>vkm+Ev)CrmnNvP=)- zjth!-a5)GlJE9^-Q2`ObLD}3<+(FzyT#g8+$Kx*^@4NTgUDX3Fb57^JTd&^xy!)zd zUe&!XXQ)awa;Z+Uw3p^+AMK}kI*S&lK?mq;I!KGOL`^y;^7+UebcoL7|Fh@r$V0p( z@Xp9xk%u{=|3KstIuf}p@(7(r=SNOO?x)v8?xWYz>mvW4*ON!f)S?yg>1gCKTBSC1 z=mI(xxr#G;SM#qnZsADzH5@s1}i|y`A1c@1%FpCG>834_!*{hQ>NH@{VybJ#p`Z#@pcM#l4pQ79Nzr_4BeTHtQ&(h~O<9i3) zNq5l~=x+KV-9ulZd+9#09(|`VKux-=*)- zWAuIc0sWAEL_emV&`;@cdV+pNPtwon7xYW|75$oiL%*e`=xO>LJwv~zKhPiPPyEZX zKhv}H7kZAKrx)n2^tb3jbACQC?sfR#G7DK!S*|6@YhG*6?YO6D7jn|HL{S&EHP?p}TOc}BgueChxG`^yu#sqJaaDn0{MT3mHitYEaf;WHXRfdX}Fo*F5b#y&6(ddxKV~ zc2JJ)UG@giHh;wDMxE}8AMc1r%)y2ZY?xCUIyzl*7;Q)8#N57#&IPG`LBFXBf^vF) zXdvlh+mzLT@AtZ1Z>7_U&wH)$$d7kLr02uubwf&gUZ$d_mjywEaS; zNxBzO;tSfor&HVW*89WJpugVs$?dI@-&;*IV0<6OH`MsPh^a<<+*|bq)Lf>%lg(Q8yZw#Wh+j^JQ!5>R;1Bsl&S;b6?t0skV$$pNM}F7ucxiWi z*x@OV!#mv(>gV{&LJp-HYaR1#qDnJ#@?>MpU)7U#clh*eteCK(6@TQ#W}ZQaw6X%ZqMj^y}QtXuXZK z%+BOcZ$mneo9znF_3pMadUxAct?Z26-F8OrXFF5F`7UH#r3JnPzNO={E$}VyE$}Vy zE%4!8wgo=C%Z7K^7WfwU7WfwUSkCM$_*w9?;Ag?lf}aIH3w{>%XTi^^ciUOmp9Mb) zeir;J_&M0013w3T4*VSWIq-Af=fKZ_p94P!eh&N`_&M-%;OD@%!MDM;!MDM;!MDM; z!MDM;!MDM;!MDM;!MDM;!MDM8z<0oRz<0oRz<0oRz<0oRz<0oRz<0oRz<0oRz<0pU zgP#WGWcci z%ix#6FN0qOpWg+{JAz#XzYKl_{0jIL@GIa~z^{N`0lxx%1^f#574R$I<2k~vfL{T> z0)7?zD)?3KtKe6`uYz9%zY2a8{3`fW@T=fgVSg3;D)?3KYv5yDvTNYiz^{Q{1AlY9 zs)1hvzXpB{{2KT*@N3}Lz^{Stg73n97kn3d7kn3d7xug0yWqRvyWqRvyWqRvyWqRv z*TJuYUkASqejWTe_;v8>;Mc*ggI@=~4t^c{I{0<)>&kbq?mJlb9jyBf)_o_Vd?%xP zC!>5PqkJc$dZfur}|5>j3J4^JZ{?5A0H%qaXrP#|->}4tTvJ`t+ z%6zkw`DQ8e%~Ix@rOY==v6rRTYq{$0EWuZQXB~X?ch^06SAS<6eD!zM z!B>B09enk7%T<48Dfb&o@YUa02Vec2b@0{SSqESJoptcl-&qG={hf92)!!{w{hcNF z>hG*${?*@E$Na0mvyS;!e`g)@ul~+D=3o7tb{oxc+`1J%tT*mOBJ}Q5Z|7Rj)!SJIUA>)krPuXo zD$AiK)1IYR#ZqRKrC7yMW|gJ%%Ti{QrS!{EW|gJ%%Ti{QrC4S1w^Ndq8@Bobe`UEl zb>Wy_AWbN1z$rUrXPx+3r)Od*Lw;NBtt9;uEq(#wv$eipCws&3xW&9}Q7jD8(l3FmW#yATXCv3Vk-w7Uh?#E^-0k$J&2bzp4^u}w$2ZIA zArGv#SrH0=nBMEIe)ZMs`qjv?mKbgH&*ZVaEQlR!yy+K0kqpcmrynn$Ib3V4$15tTDrzcR6?GM}D)y?FQ?XCQeiid7&Qh_UqM_n! z6$e!;s#sFdRB?`qLn_WyaahF>5mRE%<}4)mLYPTYE4PeJ%2hEHJCF9q11<2iF@>aD z7%9oskxC9P42K*+N^Zqfk}KY@kjHT6Oxm+lVQBs~M2e$z#WmHn$ zRo+}k!l2ub~U#5*9`U14E51Gt&d&J?d=W+=cW-M*9p<^xRlcfj%!6V zXfYFtlA}^$ky_T!xb}dExK?O5T*}iyFdQdpd=V!Gz0HIo;95B=E+FOI;jp(HnF)ov z^>mGHOF50$HY$RCICdpj0I8Us+lowzJ`;*=%YohDu(tN45p1mu$FETvn3FV7Ydxw_ zYi$#bS)(>+!vR1^CuoI+q@}!PTR>W?H4ZK1-Qg%SYJ*-=8he)GGoi?{9GF_%<|K=u zW*U6f?lj;mX67Lf+b!JcD z4pVEE3bX57HLjDRd}LzBsmPQ6BNO-0m(0ce_w3zEw+UzEUYwJ=;Xh>MuHBZ+`~TZL z%lSN$(K9(clhreMJ(JlpxxEKDPk23N_)Lz^Wcf^<&t&>cuFquqOuo-#{7lZzWc^Iu z&t(2I_h+(yCjVzLfF=iMvVbNJXflB&7ihA9CLd@rf+i%jA zo#mZ2ui!m4m-0@Y%XmNkt9S>^O}ta*W4w>1!8>s7<=r`_IG=lzcU?ZpyI~&VT_MLK z&+y)tOL>pX-+52YKY6FfmAtzp#ycl=?wE?)%sX4oh}_D%S*nrSWsk`dxPK;jchM_f ibf0mh{4;k}a9oyQmZSKsDy<^+9ZQHhO+qP}n{N_F1`E^ot-JNt@-Ra~<(w(Z? zSw>hG00j7HF9iUk9|2U+0{{kD{ZI3Mo3OBg)DJJ@N00L#Yz+I7L)rhiCFLCioA6PLhry@`?gKyoa9&>;V8^BLjX7NEvxL#-BdI59fyu&}myf zOVYR0wE+MiCIA2sLI40XNMc+7NZ-lf#}6X=4@dL|8M=2UnnpIpmH+_M4FCXE0sufK z@1m^V80*^q*gpN(0wDhv2*wt!MgRaNGXOAl0svC!F(M+mG%?gQ_=zLohr{|GUWE|g zO@5R=y8mo{|9}_<1ccSZ(!u2?z8@}_F#rG;0WEa@ZDFnd!$b7>iLw3%N7vbj8=SU#k3FH_EN`TZwY>uXaMS?+Aix0tgk&DiQ`t6l zhCj9lDL=NEKd54Jw1 zfA;cct-$|j0RWc_eH{ax9nm-UL|$C*>Kcg|8t{R^qo@Bw z*O3hYXGHz;;Ww722M&?5qa9Vyt&EAm9+%R9ih*(b&csMxqf%=HDAxxCOv537{lt}+ zY$=(fh%sE<4`*2cZ}OVUap~Ds2TCO?Igy~3fKr>9KY-$>h9Z_qQV;X4iv%D(EHbD3jB z>({qM7%2mvFVx2rgyjyYY^Zy;AF2*qm9wvL|8rN|bx!xL8-fK8Sr2dx#s)N;ziS7&j%jdt%9E$2kG$+zE$)0D;>GZ>wGm{OQAYEYZFYOu6=IrPl#$hWW$R~R) z_57&hHeXElJHfxC`;E`u`EsiL%xaJ{{M~)An_HpY5Ky*7@n05Rc|DAJ@~tk6lFsKZ zdLGHFDvSURevvvbSD$cKK+Zm^JM5plILb_Dn~0p#`;s%sNWtW`Lpi_whW0#Xq`TpV zQJ&f<1Y`p864(V@)7DUPeHf^AG@Rk`6C3#Anu_T9H5|T-`#2o!J@QZOjuu4E>_4F% zxVA{`t(iR$6I7Dz)AHR*@YS2O+~iR8o!9WrB)6=Myb)m=;3vzU|*w2>^x1dX^R*Ph(|7|*g=sVSxH92Y?GIeP@>t2SHaEzTBvR0Uf@;((F_*Q{T z4hl>$acX%wcdHxUaiBC!URp_=t1-Vx^SnTJb6K43FsO4jK)o?Gz@))tMx@z*WNBYr z6d4xF#7{h!_9C#G%SeDf0GKlwZW)x-@Y<=93yPcdyLjs!70vYpS3e0>^sY-G=n!zQ`RN8 z9#}5QK5jWp4Noh##`2aJYItbMr7Qa-_i(@EMcP{Af3L}TxUjvak1#YLR?4V8_Rd!Ic$s_Yke+!;S} zoS3^GxO3j+e|dVreCWix7M)8!&)#}erTz7mZXR8ev)JrXxx5%VkLXpy(Uq_R!wG$Tu|ecg`X*f%9vfaLe=AO6g$nw|C#)Hq7EWV8`+53# zpm<;8%TeohPrKXk2*Vlm1bQ@T4)-C=yIOj8oXO$r*#`zWd6II&RuFVIe0c_>Ph&U4HI>8_WYMw z4ac}W-4p(OBUdy=g?jv8ZT0?Egrgawg^G9ow|$K@2G6kd)C%GkUjPnE>YwlIS(cne z3y^7d>;loQWXC$WEr3uQ9rOX1tBh5m(`Y;nW{mI$C$&hysHBjT8gZ&o5oWj=%aDdy z-Q;#06EiL?fZ2_z0U^KDVr8T^O+@{M~nRErj;Fe#cBG-E314$VQ^*Ct+z%Fyaf z(RKzUOOd{#H?v>rJnF7_)|RR@KB^|~@N?juGe76-%8JI^|94)>rE;lBq9-IG^w*r#_d4jRk$niQe3<- zQB&`_;d?|acleyy(p=>DOw}!lc0s63zszMn2Tb{ zz&K2wYd*73I(|OsesD0lpByR=Qdlu9;2+7tul%?9F`R#%W(wPwsQG2M!j0NdW6Q!q z7SWNK7S3zG@&$^|U@9G>{!K1{<(K6PFMiW0Zibl6k(4bVE@}&ts1$wSeIjLsPYHI; z=9aLkp`r>pVFU#CU*+(5P;Vfy221H`wvbZ8fAm0a>%w=;*Zh+6e_^u*R-wz7In$o_A!xWkuNq@w5hw)ZrOlBB5(81YH)tR#a zqmVQ}iWg%Ul_JW7VQdYfkYs7?!b+!(Php2!)%Xk7sxj`UA%i#H>WiJ)D`{klT%X!M zIbn$RI#KK+fF?U25Jr)kAe8V=8Z438=$AyP9%ge*25Ln?n!4(sWyO)xl@6@Ast9c3 zLT#2CmPtXV5$lXV`K@zpvggGyCfxjAI=b0ms*VX;aF0l4y@RcD_R{Q3Jd-~y)YS61Sjyit4fDBe zC&xTaHL>pns*2*}YeSt5;v|+A2JqA6Fo_iR#M)tnf>4G)#)eGUC4qGsN)n0G*l(Y5 zLrxTNa;g(nSqA7bx1gIi%+A9=S^F`nchq!oJCNv$oQpk5isfeuZg~G9%d{3hV6hm! z0{_dADwRy_=aoUV*bX=s(6N-zad=yEgu^KhdV|-i~7(Z)tc!3sc1iU&-L~6 z*^|_?2o2h}?kkm^OHwjcf)zw4CT5$gl#7)CT6ufVV#I3=0WAHX#~*)5;3s@jFD85* zu|z}#)jva6j}sIZ;beml1ZSAo!_%q<6MUz|mDAy1D%obkN6chLUQGOfv`O534doSw zb*w!me?vJJ7L|$#OLG>IdnU=FXN{DBY@&J?r8tu^l|u`b~Mi_Jq5e}EjkC0kjU(-==lgZ<`O$ybh~zqAe=x2hUFu~N9o z$VQ>IEH!mA&FnRzAwW_$=oDjfhfulx*LBrmG|9y>r1F8I+i%NQDnvBxru*0Bcp+z@ zPpIyMguytGe!g{DQPpAxBNEa6H8?Ys=I%U7nw?zUwgzJFhqk?a5rck<6`lB0RN|@a zYMT!;4MEdu-QRFZ236YM)6~l^D_mr6WrlkfMhwGFSH69`)$kcqY zc>+fu!Qxol4kZ=6M8R8%;8Mxj{lm{Y`|U02Jt9f09tN&JymbjTv4@Nv2C4zk)XF`W{b@a#irlj1sBPastO;_L*AFxh|Hl8{uHc=G{IKSX2q24tFKJPyregMXJ>kC@qw zY6uD@Bl6+!u4*$oX*iyQm1UH3G<<0*FzZ4*l#_?nDxjdw9_$KHUO%`=tqwFmsGO^W zr<^#>YiRgfrEat1d?{#@mCWDmOR=lH=;)ik#zdowIEaTBTl~`Dcvv=)%Cfh zsg7pBYi{|1S;&{J*7=^^YvC4#Jj=FSFlj9$COq!Z;u&|W07tn%biPT$B-f-Eg0Lji z%>2J5=>)`SCz+Blw-ebsN?6OJk=$?UP_+O(sy$URu*fB;VW7$bnF3tHHi zF{9LR2{0KU#ojktbQojz;TMkF%po*;VXYemDb&#pqQIxxb2vU(W}{gU!{siCIAHDK zxaq-8BHf$5FaHfE(VAOOVzY#$GSOHQr!WBqvr`${=Bd#6%J?ogWhu0H7nZ zKQRex9c?e01f}@rQ5ctXf|e~=uw0p*_|(yn8usF5*<|qOd(rcP_c}Rk0E$D-nhWRU z#GWzemW|y@9S(^;L?6Wt`8Qore`qz=kxiFCGDA3ic3!uCraA4zJnBw+Sd~BnyE*S2 zCDuyKwZPH|Z@56BIs&*+Z*B3ok-Yz~Y1#4S)$YQIh}2aMB?h~{Vp>e7Mp zr%UZ8_z^K2cs)Ev^exjk;Mxqqy&y--fG#6Af9sTf0zEkY6b{-RUV99Ol>VG?9B_!R zs^~e75r{Rwn^L~|pY2nxK3(MCYt&7QTJIfyqwf;LdhfZAQa-A($dc|GetGZ3kkW3` zfra2OtEiIbmz>gW^MM6EX1z20M+d@W%&*&nq*9wdtA|hVyKIB65UxH_7C&|9%~r1s zA-NtAk-qi;_)sPe3=YgF7&higMiXNT_IN$LiSG)WMpuLqju{T&1vQQ=5Fa=?D+sHq zQVk$^UTYV;3nT+V1s6jFgWZ?VL)sk^0|TcAfx2&Er|w^1EfKw*|6h>-;UkpfNHc;h z+9+^vVYJ|=gBZw|I8g#Xs%3v}@9&|hzWhf2Tkmu5q^(HFKbI90w1B`$ilCoz`M)}u z0Qds5?-XWUm5u(V;$@)!koce4`*Gx(joRyb`{N$`HfFKLN~ab$tY5Jf53F3GNA?+E zk(mHrHw)1p5dfRcoa&O{*y}C2777fwnM%7F$fUueSYtF z^8Wkx{TIpb8|cv=JW$9};8J8ik1Bt0HtVGDq?+L*B>_VS2B+SU-=)_@7oA3+eAc)& zOyzF{lM|;C(bLJ^N%R;#kL|5(rfqLarUW`21ud+WTAKrwOc=yo`~GHfKJ7iNj5hCJ zgTBrLlLKVMx_oX7t@DLTbTLP+}AAD?AD~$R5^J+rP}B`X+Q1X zmLKRD!c@di5Y^!RL3*o8g>VGx~}QZN%SA2Ba6*I>+pxby=D$i&1liDM23T*Y=J zg-BCQM;?r(jH(Q*Vj>N=R;98?>Eiw#;NJay<%W(o9I-QSt@BfrP(4?5M`1Kf@smBG z$fi(F=)V}dXuD{#kYY{X$?%kHl-pb&a7=CE=gASa8r&q@$lKc6sGC1w_94w{oKa}t zO^bI*nUBpMuRUt9FS1XvTe5qy>zbc+z{!*}o_Bn(eEUaBiJmSoW_YM{7DOw>~uA_8AIe3N934!rwp#wOnJ?!lK9`8<}sUsX?O@7OAJwL9T@wJdnPJd+Ylm zic@O14BYskrg&*_X@%P*trfh0`$hZVS;$+OCHq~(`$6#K`{MiHE8!QPAX-MEHX32j z4z%fGn!|#^yn^iqdoS0)tT>j8Re)dU4qpnt2!Cua${1{+j+T_k*2GeV#fI&S1&>8^ zN8T#=^$*W9%(RasHf=y^t7zXy>wX7c(c7Y7p!r7aO}&eokdKjj&C0O3iWiM9iPy@t zV^wLU$Xwle-8%eZd?stD>-M@7?lilBkI!k2b9c&GhFm5>MnI;ELiXD?!NoAEPVH0< zj|VJkif>aXSHU4s@=)orG)lpEntoa?`;cd!n~7UpX}HAo%<8ehjlZ)jikpn@+Jm=P z*VHe~a5Bh98F?wgWUBqHZLNJlGpOpd%4XS=txbKl^V{#i@2RhR(41loiAF}f*m99@ z%|=E+MlQNxc$sPWzSTJ2xcRspuCo6`&d~uk2lP!-;qDFnrFBMi`d3R&yG*<4x%jF1`T9BdT}H}8K8|8gkPV2m zwsf$7^)VG(3TQsUbhg20jVbew2_$^%Z&n4^Q39|9h)4naTp3x&HQ%U7a;7Co=K4wC z`i%|UrPNEKXxE_*y)AnD6e1g(448QxT54Y|T?D5dEf+Mcz~-I5FB@?tVvPr?fbf+$ zvso2_@a4Nvq`C{0s7i9GCGont3J>$l#>uieKc(QspB}C1a;5tc^12XquW+NSg-80r zlJ5NK1#7hBP?O$zgXep<%mq2uP?p*8+M&}7+A0_(*&cUMi16E@E1N=y$Xc zB9ZgMp8NIt<@@UU!TZKtF4}d`NBb`UT}Ihs%g6R_9$l*2Vb=4{lg?++&t&hWURBx$ z)=yNQ!rk-N_tS66AJ{-{KG+E02S7pqm=%z#o>5RYU^f0V9jP0#0%Tm|wNP);CbB35 z6h9$RNa$T6xdPxl80IFd^^L4;e9hrZ?`*1(#=@E19%|!_uK~PE!gx_ z$<`6H`FO9V*r-k?XR5vL%<=AAxamw;#%!b!<3m}*q0_DF4}?mI4AYo-?msHk`E1y6 zgoJKDx~IP`%Fj8hoTF9`1z@iBA~YelO8mNa1h`s# zxNVU0g{LJD5fR1TSe5eY)Lh<>zvVk2virsto%iKGYUE6kd#VNBP3l{(hV8$Wz`I-58GV zCh_g&i1YV^S_ZGz0DE=3w~xt?s>5Xuhl%e>cqm~E7+?2$LfnGo27hpoXLQS87%;cM zliS-;2A3!B0Nc~pCkIRiGo&$LCK;b07_o!f6NT(!Mrn&c`XSCoyCfZQAxzif4cuAi z>+*LECKN_W#!=)k)k;~@*DraX>o=<{h_S21TN^Q(GP)WdA!iPh5&gw%RnrGUfYzuz zXvKIU=z4yMlQ)N=k+?GDaXm%rN>!_CF*%3JkmFcrc~}r{_uR1=9xduWA0xd>gP<;? zGKX=of6mGn2vUULhK8qh2K&BCp7nm=e|=NB*EGLN+jwd@2zkuo$JpUzIDOYqvp;wZ|RZNmFDAjasBEnlsTGAMAtmL*E(2s57kW}Q6 z(_rD+8uUS{sg>Kx$4sJJJ}LzTEkW8H|M%8C4GMr+GGjvd288mbFYX>v)WpOtOBkA< zuS$1_cS6&)!h|t3O^F=~*FTa}em{q3RW~e}jUx^_K70gUXf!?<#~;*aX7(VMg18wf zKHbAR!_M|zlK^)~@-wR)#$o&q+=35lo8lBk)}Tid2T9U?4LC+%WjTIy;AJd0^Ia^A zeo^`$%zj0(ZdCl2k&bb}1n3V+7}kv=M2Y<(Jd9Yu&AXpeKGHn$5+}8U%HxNuDfIT$9MKOjTrj!g?|lCspspv zDKMxs^H`0K1<5!V_vI}X=`Z>0N+&=RqEZDZ(Dvfv6@mhZDEkm%bwZ$O(1{Wv2*r`K zCqT~LZ(YAiY(Sqc2;uh*1;DvT)j{gSp9BhUjtzjfZJ$nLgXpzDEreQAoA(Zjg1&Mc zUBQ>1w2JGU+s9+rxEHjo_0r&Fy1qX?J%6p&(S0es+*0LML-M_C#=D*)yTNODd*9Lb zUW0#BGTn#-+1dGrhXPoQev(m{y+sSEUOwtQXS(gPoEL0KNs^szuNpSp&eu^HTezL! z)@&YKt?U`+?|VWo2cXZu^WCm+fqxlXoDN?dF*^i-8bgdOcx6Gqs=@}K97&f}U6=aK z@?5Fmd%;PST9$)?^|ECK%q{xxBBDMY$c9sl-KsK&WS}mKv$QEY+Tf}Yr>em}(q|d0 zemx_Zz;>#GC>Xyu!4b(K)*QS0{{Dr1Cz(&~ZWzWM(|M*)DEuo<*;IFHs5np&xzEhQ z%rDbh-e!-@dT%`8%CnEX9{m&eCaC>*+(j725(l#~Dul})dY~h472DFzIO3?ln~uqS z@NRG|uI&DjF6MZ4I#uJz^T@qsTB~de2;tDNA=o_x7ucqqa2W<3nX81_&z6w}6~EwlM;WpiV0Jd-h-IcNR)hms@umBR7qfg;$l!K_XR_ zj_!Xk++RGM@wrA&T)V5e8}45`BTjeThq1Auy1fya@jbo;_4h-c;i0~xwAtO>DwjC} zjv%Bxo)sAby@P$nbfg(kPL=NH+2Iy@Y%)rIXH>|P36H8fqA9WdzA%K*-EfZ5`ue3A z?=pVm^5-UpysXOFO)FjJR#K~a z!+!gJNtP0glZ_o3mxqOyY49enx%m!iD!CW;Rn&^4Dpj;pXSI`n$6D}~bipdL=|ux2 zo!>lEet})U7DYW@Zt$j{G*a=`k`sNXqr(ulIr^H)C)z#5I&Y=kR2jf^9&Y+>i}iim ztGU26!`6DII?#VN15DnaZtR#k$Usorak-NiFjL}vIeJE2Fo&aiL=A9=&Xb=={LuYg ziB8KN8b%x<ALCVG-|%igr{FG zCwuqD;`I&v6S4kou2I^z(r_ica@^0O2jbSgm1)vdslR?~HoAfsCta^(Zq`B)<1 zeWWyyo8|KY^p|g!V}Vff1)6yvR~7J#Xf@W>)(6Q-Vro-D%>wgjq4T>I(K>$r+31iSyR)O zuU53T7;ZY#qb}HIxxj9}@xl^;WxK5}~t7pup-crBo z=xCQs$CB7_ZmgtE^>$L@<>fOFP551kHZEC#vPT$Hx*Y8$eiL53d1lA~Ii(Kp?o43L zGa#)B7e^{h!}Eh%$dVH>IlAhY1=R880a)1eF6~lR%EpMg{s1U$RK81h+b+mihZY+u zbS^n|G9Qyg(6-uvtAteCr@rnQ&Zbwh-UtgzZCgQ7MAGHfz5|9fYt1H74Wy#2y1!ee zQ0cap(>irNxB6KQCAK_HYiSf^_Owa4uh~I4 zBm!IEvx{2cyED;(z0-=6QLUWlIbdJ!%TN;j_~LSTXXv=(GO*?i4{m{ZQr+R@5Vt2o zzMRrq2=}>PaU!7D)k|8#$-|elfbHwWjCWtnJizC=X1H#qoq6Vq-r94}0P*At-u>HY^zdnIZb|Xnfz|zH*v+#3lq$`u+l?&kw!d}Aq&eZr^R5O_pl-<}Vw|uG zIV{m8t75(Yob9u_W_N$n0hI4}zrVEyKIjM^UAPBeM#o3Te0Ketfaw4q66g|AZer?E z5>$Hk5J3nxC~(pgQxfI0bK5LQm!%UaJ*fG|ZOMFXRrJ-RY+Mv98SlA#eKt)-VwSC{ z^2=+9Y|L1h>e<~k-*Fle+qqR~n&!xx&kM;L{9mpyM4Kn0Z?~c; zo(3>*dTZ$@)Yt~Y+>||xS>@r*BH_uHLNUPgP}{g&Q$)Om00Vw%JGQrAEOteNi#?T;rM!k|;sDJe{kUlR$Hc zi4rLkX}gr1RM+&Z1C_qd{x8p3YN!jw_AsQ(_GBpv+zR_9N){@ORuXM%N(zXsJ z+HhDUl7MrZH_?g1O7_M2k5fxUob39y(O6>TS{h1{B~8V6yN}^#lv@qq%dky&nzg65 zO)G1j?8Nx>I0I49I@WbLRmbsp2((sQu)(cQ<-RzI36<>HHGX8B8iYx!g?jUG7;=Z4nX}t3BSf^(f5W(Z)EU?_&QEMF}L1n zIuu)y@xRLgL-m^o%9N{szwmnS1DVN#2au0|)Z^Jk7*^6Px~G>5m7uPYLg~Vzgvp01 zmW9pp=J)h=bRElpQ6hv=(*}U)kZF*GEQAdyYq%<+`I9Nv62T`GJvz_NzR)6ArdaKD ztrLNoFS?rqUvQlqY+Fb)D$D{S<=k)!f3Ln8@$B?E)Pj`sQ zq3G>b-`Ogt&TZS=#u_J7Gc+1Tb~Oy5iQpg~pObwyY6#NT1r~_LZ)!AMk;c>@?8b}9 zdx4WsNIn_}!o{#n=f-~hqJXdkFCXEb#bT0}fR=?4!!cyA8vQ8BoUS^-Ty$}Q(QJC*`9T&ygmQP)aOXZH4zlivK}dYRT%LGUqmH?BTTqq!cHVeMJ`_z`=l znRIultej-2l8~;t+-$Y*RAuSVQq4Qxq2r0E`5dgPDXgP;GqV!5VD7pZh42dpJ59y$OxbCtUh7&d{gWu5Xl2XKHD~2ce8S2x9N~Di0BEi-wz#5 zIuPbo2mX1>_BGM0?!j~baw$;HKQ+7kPRzprg_=9mz%Cs9`?j}gUcD`2wB`W}dRUqo zucNJ<;^Yv){&Q@st~aP7LAGK6jk%h7p3bB!#3%s%2Ew{RGql!mRC5^LynW+sB~(+w zf<#{iE~&zFgqejJf7Qf&h?kXdMyF2&QD1U!F*@dz8}LAp+aTje_ItMBlq5q|Lq=dI z@05HNCxc%AU&XU9kgD~_^QiSW<;ncdwc$t0Grti??=#MhMBa15dAT z+E7W{QVjXy@e1OuZHK`fq!oJB?l6A4=R+TuRm#qVeu=Qnx7Cwn(B^HjRR3_)^f^PdzLEi%fnM!j`He68|qbEVk3AEem0D%m!W&1`NQqu zRAMA%D|E1C0)A+R8}Jre^vZm1j{h#KBMj-Tt5ShjfH)?lH|zXvX(o5 z@4mK&aTK3PW&?%Lmp00lbgkX_PP6Bob*B=%gFDPoNnz=bj=NVv2QO9`y| zc8O2tAsxLxpu6fzWF?%w$>9hjW5DEa(o1Fg83$N`Qyf5y=DmKJ|RC_O+5oq`fUFszG(1KB{p}W>{FQvi8N0 zn~tHlsCr>jIX<2pUq2?|rnI4(lZyeA={*gPr?!3A>bmuP;I*iDr+>5ap+At6)cf=1 zPB^~R_VvbXoMb#`w^x|ywdQyBTJWFn%7mxefo@@HcwQE+OXyb|>VQ3ceu1F8*HUrJ zU!sWogn{>;VHBv=sXh1)n(NCeE!S$hCw^iLJ&ogq(B{4@-3pzwr!&kq=pB;T>pu!Pd;?o3*L^1i+|2UuAr z+^Bk5@{Uf47a8TrIOKe2%Rig!>gy+?Bofk5v;ej3f#0F6j#QLX;O8YvzTH%m$_s}G zYgtyFdlNjZ-_GaTggBnh8Ll0M&d?rL&N1*ZP4rKb`BdqXtCLhBZ0k=etk$5gF!-!i zP4c)7ASdlWC)mDmqaA$%qH!|P60}L#o%8Zca-VnJX+0`%OCd6^Odzt`o&7%8eZrW{QnTXHQZ+ z_2oWGBqMuMsh&e1>-=HkG7#)x(3VRZ7M2C6csDWsB;PyYT#OfT7~)@iQXo*JFG!51 zOB!!yJE74oy6a3_Y$W{LtOHy7@Q=gJc!^<0?DYz~rJmH>C(rA6Z zjD;ySwz-HvOu(lku8UlDx;Vqc-pz+8DFnrplLR@nditFU^$w!mAZmZcMzhnMUHJdW zXY4_gcmNMI4Kq##8j_|CTP$_t&J7Wd8=(vrj~k_&nxt2B=4rNjwC5_LXPVOednxPq zxTeOFBDWv^)_Z(yYSD5W$p3U4|29Vx4t*iflu*YP{H)Z!;ykMoyoSp^ghy||(8oU^ z2R$FmwT)B}{p;0wAI9oinMSZK)^@q?{^ z7tpF{=rEeo^G)M{@-v*yRf;{j!ecl;{-v(3i|O zYPlRxXX?;*qP(OcF~Eo?u?`Eh&eaesA5z##d4=qQ{t;h_wj`W8pHbXuz7KQ)i*Yd{ zo<$YGgb%-TUXbYAT%OsTXh9?bhu;Y)$Zb!)Ey?|BLA>r)zj_bvLwvPfL@?~pgI;a z5ii7Ee=t5zh*q!Y%%?`+W}X>k>b|8+Vch>l2~FZ7oS`=|7j40t$L#Mb*Se$Ax*lED z(7P}i++Dx0p`rr5Zx$$NgWdSF-Hm$VCli@kgLquum^1tHH?S*0$&PXO(1{R#0|mp# zb@Y0V273MrRF&Pe&m}w(5Sk1O%YsJbLZ|eiRT#1$cScaHg*`|Z-v7Q9IxPTyLN@1o zJgjbEv#B}p<^`@B7-IR&WaARp&WwN0h+Kisp#wo`tila^V!)mB*e^Fn;OW?jBOy%$ znVwsv|3 zQ!UiAmyD9TRXh(xuST3wLvDM|f@h98WSu2TAYY6Qt@x|Zbl5}K2B>Y$TdNc5N&=(8AqPS%urQuhY)lbv3O(u9?~k2 z`GYWskkjdb!AQZ*A|w%+y_xC z9F2bb=gh-N6`nPzV{QF^h@fu-Nh$5neXhW!)9QetXF0QvDvM&3wOjD=8xjIuOddOQ zFryi5i!>tI7@fjLpro~veAVVg20nCCE?vjZBww(qHl4g?pVHSgXRfp=|VZfjGRpdQQE$R|&n;l;aK4c%Pmtx2X~Ao}!DQzeeArwjYckK>x%%GQBLz zO!S0=1ufo_0KLeRUx?e)L2~Wq*nb9oZRIb8QbDbk`gVzkXds&|o@3QxYj7a0S#C=8 zFPcVpopTMZiEBz;DVzLN9qdEiUSIjxS&Jjj|LfmPZte_^YlZguu9fqbqyksPVdT!SMQSi?r0DOq zT6XPoXFqIZaCfH{|7O;fUs9d4zGrUGXIHIj1MfnUn=bFo3g%3txk0K<@5<)ueeWjJ z;ElhFMvbfmpNxE|s6zqh074{b*in>R;XFkm)E)(L|0w0GCLA%`VCX{)j<@;?#gq*k z-<*6?J@pv-!CE~!A1SqdHpfQI-G-TZ!dle$pK@Qr)nG)g(xZVAZQ}S9zWS{zD@2z;(fvJ5f5^lH#Pcb zt`!qz3`a_uQ2iH-ajSoC6Kd_`a2YPN*`Z1|xp}eB;}Fv7{g~K<y+NPBV5i>Wvrzc zjH3*4J1Z1S7fcuE9dx-C39$^jw6aL^`2ihyH)Cf{{+>&rn(5pkQpm^`e=o;vuEs=y zJ8&nMo-cZFS>nADW?4KTh8Cu}e>EjzrEXw$4V0eV-yv~gY0pTM=iVZT+j=*ELI~b% z>qfLV+acp2M(s$u`*s4ptdF6{Am}u7zCyK`k`q#-1_ufGK2=JLxpp^aMgK~_^tkK$ z?<)3e&bfta6|h5P8>@!vBAh{$Pv6I(_%*C7rRMjhN~Y|K z?;EKDeNGRdZh7e+2L2A_et{XUXW!~9i|zE$W=l*+k(4H@z)U&YFe6yxR(NHE?S4U* zq6iZXqPP{(+uNL7sLI1P-ni{>7$%4P`sk@tSGWBh7Qp>FHh#%=4}3Q?vD?MtCSdP; z{-yEl|mK?0wLP&5IfRB^_tkXq(I41V|%NmDf?Kf3zb(@iE;w`dV^QEL3M0S^{cQ zcVA;Sr$3VID0xSpjFeA@32rCEK!4!?+rr2cmGztq{}{^ieH!vUTsV?WNYC^;R;=WN zHGj6;XA*tV--$f6ordS?^@agUsNBH}7S>V-!a{(-H!i|?_am=-k5-c6lveHT&k(4x zi|#IC29t|bWpkoykx@@#O@Z#61O|?OlW&%pe=QZ{* zQQc+Ofu!v9q-}1_QG^8dtzxD>ai$hi7M}$?^?X?$-e7Aw+Z zt2Mk+`;Kp0LF&!H~c&m6IPKX4}M03)oC12BkjA0J*ZH%?D3Q7b|d)0oUsD)9NtIlCipGXKf zEp1nL8m*IZSv7r?U9S8#Rmi++jwzyFOmQ~Wv5>}!lyWssIT^OUfj^*+cO;Obd`8?f z`=0*SA@|b8h!wg|%L(qx$W0GVB$4kyXu16**iwabPs3=}+cCVs^qO5s8O z!vL`dF=?jZgSoc4d|R-ji5V63YR75)H}!pfLu3tPD)^+$6!bdN#^xxhjx$yM!#S2w zGOD*A3>8Nmm1Cw4F_5~{1rSHJYN7uC&B}mQtHwcRg11s^) z?N``DO2S3f>UKqbN;u2`0%AQNIU8yeCcS4W>&aUME^WNLMq6dojZbVKz+dk8+1sF= zEZyW%K{Rb;_~h2?Y*ittvN1qu)h#up>0_MS?_xq75F-r3miR(sMTrF++9biyEHnn0 z@tG$3=_C8a2}et3Z2!Y<0OY#E?YLp_3dXqXdZfAp_38>UI}P-AiW(M#ttrnsB?<|7 z)esK>^HI0ZP=2jWDkJYVbKj=xCnN7=^FF1M-S`IM8)ZGSYPR-qd%s&AJrqi8Dc*qZ z5g=u%v9rM`-$mNC{LXk|(uK_aF1^9;^Y-wWhW^WENV}iE^?mClik3J_Kf9+v8Q^w> z*OTqjaJ9fb5h8y(2}*}XQ&gf+$s&*eHzN|}gOn)LQUux$9d2*4>At015{4GFFeM`< z1}PplJTN%&NYa|N!`b_Rx7C^KxFtQMvZkl+ifNB!V~o;97;R%`i-SJ0N*b|muIECc zjox1$hmnPauU94W#Pr_jz8X7U3|~_Ve+f2Yw~O(vo{DT3irwIzhgFwY}R> zcPQNSI&?H%b@^#!=Ms?$staQ8$tg{qHJtFa7eL%IqQU1Xw?g3jFYWa>S=ytWV4`+U z3`^n&>|W3y%fJj5AXQ;Ez*dYc7Z;BtwkgKW@o}U{Juzv-reF3dCdY;W_79Ea_V&b7 zu(h5>S;~l+&t6x`;Bcmo&~xB37;ZDW@u0VBoj&@qYCPRKrQX`2b#DXc9wX7n1FR_g z8K-sQ?&V7eW|Qd!;~6qN$l+i^MkE7W5tPFN3Wq_Di?}^dXwog;OBlSiHzHK5nDu3f zFs{dlFzq9@BFXV^wKDSY^vM@El8MU7Tj{>d?%uD+%|9QVHf1kGJK0iQ4Iy_@hDp^{ z&#F~RwW)BtZ0@M|K*c7kQJjw@u;82Uj{{O?6dyVq1HR2o(X2E=f&06SN; zNNdTKW<0|9jfDv$M`J}gE}I_W==4dlE+IXa$ql51(*UzxLY0g}WOO>8%uv2Y1~vv4 zQn{@Oq@U774b#3zd%?>;-R-Tl(5!r(*47*SJVWhhM=Q`#o~8!MTOz0lFbH4gp4v`P+T;x3+B)dh zC~u~JMQYfk^1>8}vA>BcDLCawWfF_kMuAfK^&4yK6Y8J>dfmeYP>zs2-pk)yG!q1F z4+3-Uq+}i*GE^09#$~r+^>14op)QPAJ>**Hjvq{2`7O=I$c*XvTx>mUdw2YCN$^BE za-F1FZQdhH_A67~tgkSX0a``47t0APDIqp1=B2l~`~(tnD2#SN+UVs5Hj%9h1M}gz^ zaS+z*8oO8gKHwLI3ADbEbFte4a51)tEV2=vc5!d2RZhNsVfS&LPOgq|cM7!xmN#i^ zjeT%kOjGRIACV>|+U2!|oS&`xKTHGzeZ`KuAoztS-VvuNn}(7QqR2=|NTFC0?L&`leOr#PV0uiyx>r2)DV7eVvuH)px%z)c4A zE$eY@+P4mu*XSMkhzR&mQ-;0&R{T}_?3;Dvl>^Ibhy?uWo;R)E=#ghr*|5w@{`JH`um=}yRQE3t9`xC?5?fd{Y-Du z;hlpu>7A#4FgEt?L!F%uy$frQz`Vd-2R=?i+2}_7xQ6(mkt$HN=@?8d-&st+6;3>h zA?Ihw;G)XGJL7@DB|S##NW|#2jKuQ^zC_>Y)g8cTM$_nA_oKDkr zWui7>s4Ul%ixAiWKS7(=_t|3+2DWypX6i$woUKKtr#?gxBtLxW!*NR{Nhha&Pacr#W!M#m%7i-BE2 za=baz0efIK*9e~sunXL%!Cjk=FL@Ke-M0{r|q+No>zkarT1lWl_ncoTp-c(nYg3v@SE!cS-E32yW^%c zKel(4q*aw2U$|RE*Q9cDznx6T_>R}ce4kG}Ol8w5_FHTp z>(a{f^vWf+_-t}FJ3b*-8yTt1rRT&5b2;2!L0*QDT%o|)M8wE> zh8RUMkC@->D-kCp$bn^wWTwnpc#UxKlCTTkeF>LNzQ&fb9cP3-eEtl6))HR<+4Kqh*FjYH5A44Q$2UFh@pxX2(?%GiR8=dc ztVH&^W=73#D*Kf8GEONiC@ZY1#^*DdhAT-PS-hn>^BO+PJiHc%6?bTIo%Mybo@!&N ztHYjNU0H27O8q0|F#9Nf3#8$u8!@zWu6{fV#+)^$f=-4w8Mn+o_Ie<`xMk!pi;S-= zxSRDDi9?2H(;`jU2yF^oEK=Y&dsZ@eR6xv#fEdUgVnP>IHI$V*>hL*J=o~Pxyk$<5z_qE}SbwQD})fBna@RLaF;CzCT6=PCur>1YfZ_ z;~z0rKmM$&CbMIPX}e) z-F2*Of-CeM8`xc!&{oYR-+p^zX?3lT$^TsR^?nR*`FEO+Nu-ig*IVohA&Kd)>8Tt{ z6t=vt*eX@YMs;j@`L5E^yI$Uem5icl$JN2*&+M%Js)elkm&_XGBhXnPG*^eHq7Df& z!p+(=O0_`K>r3K?5`UEW87Xw4%40md2W}F(S zl`(XPv{Vk%wa@0YGn?im+B4(MAC;#So8lvl#p%iUd`!ACvv&lq35n6g$EK<0vHQjM z?O`5bzTlsOEfwJoo37nmMJsnfH_EL#3-iUf_ip%4PSNbyG@Ep%w&CRQR=4X`8Xrj{cVE@$h|>tx7q zuMULa5Wglon|*L9f_cJmHeAm(e4$W=u}5(lLXNXYNvsX#PolLkt`KY25G)Nh#;=F~ z=vxZLz7d&@Azm7cTki&CFv711{b4R9h%z58)a`GGt z&;5=XHw^lLu!TclYmj=f<>J=V$uJ8}5gVAlB4sg=4(6t~2;1?viLK!ld|NwxWA*hXm6x1E$6YgFDf^un|R=?iny`ewd}`IM@IpOz+pc zYY2sjc$nFE4*KydMxpo#3FZlDJyRs#Jq$&VOr!|n+>%rlnSz(~A_XFLWMHidC_ztP z;RLZkg20P6VwTiQfhD4%|FDJSp7H(x3*X=VHj~3t2-g^F7Jh{B^2xvclfk{hqx|?8 z!FU=#wlLoo_rMyVk<=W)c#W_-WN4>NyiV(9DD5*P+8?I0#{sk#VN(1sThVq(dmKP} z5vIlm1GL{sX@&!6KO4^wa4LlfpewBbq2tMx#?w7#JR(erA7(46o--a1rp5;Y}3#Ou!UrqxQ3QWsW5YnWjCPzi8BH)Se zRHZTqb{S|a>vY+ZO5?A4g1;vI`@aK=pQ?WuQ2liBm(1DI%&veEDCVr!8&Coz#L_jS zH5Zhp^Cg~MOL-ax@HDNZkQV@qRif)TJS_43@C+EMA7(4M53iMA*3N)g;)4OY9t4>q z!i>y-S>cCSicaHA63nKrdDjq9iFgKE<7(>+m2g>YeWgKsCw#g?hyZbqyrk2 zlelOi<`_pohB0NnjOT)>vo4xJEb9_8>%^Mb>C8rxNo7*$>4`TfHX%ukDiYi!g%RW= zn1u!AlW;U`xDm?9NhT?6x!Knme*(r&B6NsVurA{5gBo@MytPl@C|3_103c zCZ+Ih*W|a2*-}jk(4FSq%cFtrMG_ypjGH80X_D4Pgo*USY(8xS66sy*@gfP&B1w*30+^++2g6Y!%6Ef1CkIK2coKF3 zX9xGoXvvwc$`8;aDib0j06bioo~j^fPMPX+F^My$f{&7iiF>hn?8eU0(w#TPgwG}> zu)1kOy;fT{+Qg3wzbIM%$dV3eq^fev)cL_O~5FZr#|BvWKqCNt?pnA zX1O#H3#$_?@kmk%$CBO<#4cid*+wz`%QW9eN{y=|2k;@KB}PM1f)3oXC{imI;FGB% zlQ{LP961;}2WpzLN@*6j_h!+mBklEj`U=u>45o^f3X^5=t_EXgYei&6gteqHExRI1 zO|F|GleNi_Nx3B{{hKjYGBUoU#JF(RqUJRV8}rO{RaI>RrR{eu%m`7%g+Ck;9~~B- zSPR3z%Cz;frazm|46z| z*7k0&8!3dEF0BtnCiB4nAMHi4B24T|m~cPLQjmDbB24lO82`IuXefkYVJH?qj#}S+ zyg0Z|yx&JKuqc!C;G#JTHDJN7cCSbUgQ~&CDCBmQK?)EKU?Z~}GZKuMd7!u%d4FgS z!?Jw04D)<-eOL&iP@rx+pAkD-)H;hXYHqCUsOu;%E3R?YQ@LAHYDu2_L1rS>X^I*%lkLVBqMyL_uy9R4`&!ZVs26Pyn(NDd z0@v$B{y7q`^8Wk3^55UOBTBp<6>wiB_ua>xcg2bKG-}n6B=&So{D+< zzJbZf`7!h3Erw`E-=136)@4QR(Z~Cd&&D#+y}OXE(bDb7BBhc=8q+*FDnr`EHMoDK z3=!{tV|vSZ&I*)jVaLnuIYfNU5=*EtXOB0Za? z)$YD*Zc>}W5nGT0H>*Qxufg%nS}i$_7872rGZI__eJai~8OQ#{d(n3U!}$N`yonv; z7{*jwJSj|{$84M0%C&J5panCKjo2_D3UJ%A&1tC|&&5SEjAX-X08PY>`s&B41N#zX zWU7p_GuY%wIB~j8gPfXKBBLZLhEb>H>kU}+4{45~W4Wnz`|_pB$=|kRnRVNj_phGF z$-#>fOZ7BOaWKmyT(wt_)I~96Q5|{W-TF_D(5yw3^7Om4e>~BB&cVDCrX(qg?Pna` z<~WkYNY{eqG4b!hT6By2a9_aA^56fy|Nho7EZ)a~_doaD$DNyb@jid&=fMXN_oZ~7 z=I7A+%X~I43V6eGekJIBl3!Wqwv%F;fc#3*b7sTWr%v8EZ&LZSd6Tv^j|>i+Etr_F zpBY$rezlF3R&?*s>9;LySXY%MrcIW*ynmO!~)f@ChFLmejU3pOd;+hMF0+Yo!=+!0>Al;gyT#g4w=HQhr2=+ zi8vOCa?R;~(ZUE!AeESi_SO+DpmFUtDfg)*9NBqzCW) z7HLJ2FTGRIr8^$?2=~$!B@B85#!GS?%TXKZbhp=nX+Y}FS;$)hh125m?Da;t`|=3ibbt(muO_rQT6~Uz65x zQMp_z!5pXdBMz`1MLbJlT^av02@=pWA@|eM)`Nf!@n=# zk>T#d04#nSOZ_-J$cooXIM&Y?i`{F)X(u^X%8))_N(~c z$kgF_64_MB*&w&49P$+zQFn$K?G?+~0t7x2t^?2N&rc9kusZ@dN z4yXN|H2!ipUjjok5G&PcQCslr@;L6}xBP{1Ql;D!nwofPvVV4!9QUK!W~n+(EhdIz z_Vnq~lb7yLE9Z-+QJI}7$?PC1vvGjT7H!}OzYV-GI7pPYK_b72F}XT_+^!3lEn}%O5Ltdkn~}o zRhc@ZKnN?4|8!RB=);RgNi0hxX)Qb!Af1f)^L;H-TKMQBcxt1F5!GJbE zvqV_QF00rWh(Y%Xy|hNrf=W=GyV?SbG#{+>Pz>x;hvZ-l$~oGGeA)yMd8yua=md6v zHNVi2Ut%rMs*TY)V-VN_x=<{)+-cNO2H}h%M(nF#hY|p*e$~o_tefUYZRUf zC~17n(w#VKlGar@Y|FvdhG!Q#GLQLd9R2HE>tAnJ7%HQ1fQ%A(M&Vy?k33#n?|6}C zXfGrxw@s2vJ~~I<()vXzw;M%UZfK@$FXC9{$I*pi@v{<+XJ_D0_;GZ75nyllahUx$ zx&g->$3f-3h@<<9S>q6Nq_2|?2fGSg7v2+b2=C1p$8jGHc2wRe;^-7{&|XS3UTv1> zvHp(n>MZ#%z%)rPTD(Vs*(1fuVgTk<*heZ9O}dLIWDE-785~S99fH9W31)kV*&#Mn zaxx9Gy5i3x+ed2e3jc`wr!AXk=g;EZyGi4w4I4=7rpZaB-TMr8`0ykmU7R>{7^e!q z!l~W|zfEGdaWIZLD%<;BQZZnl`O5H8U}JzD0=tfEYL~waQ?+kI@iRdDcLA93NFW~f zJTh99My>H}_&bzU!r(z3r!uF7Kh7+#eE#_f9Kroa_&;-tEV&4iSc+}}jj1*d_SqE_50%m48N((Hd76C#i8IHQ-h5@&IiR6h!k2 zE5x%hT4yT5cT@-&q-(IK5`yWVzj4TODq@94=MMhR9g1Y{FpGe)S^v7l`q!=7cgEz~ z*S?xjT8lyZsNJcK_nWIief7FPyWLZNp#8pBuyC8jjE^{Qn0UX7;?V3TIu zq><_A$}EpNC@oSq-NVh2>aW)(Q3C3tV#mY;(=}mizq_M$duQIQmI`yRHjE#?eY|y7 zr`fo0cSnC$d~S6X&8KS-nz&~E4UkT$AT1rJ+1(I=8JSo|JP!v42X%+wprDF+VwfV2 zSQb4{eZc8v%1sCZt7eT5PM1Av; z@HQ~cpQ z!X>WI`-d&~VIkG~B)psUs*{s<=ZSvXlnvXZdD;VIm3$Cj+9coZB0eXVokF(amnCg%K%8gwOU za?dAU^&sMBr`s2Rob=Eh27v`2q$Hi>?{jQ#;APLtO0`lMN%IDEa$XWYyj4e%BALJ8 zGz@BA6hzPB1;P==$iBPp;y&*f>;&7{i)Zm~AM>A4r})mOVZE2$@yy;x{r!bvY;P#Q z+o$IU1*Es24+pIEzB&Bx9KaaqS;ImJ=J*^KaV)j|^K#GBr*rIAF>WpQ$E`j8oZ+WW z-JwQ&9tk8fj;#Z2>pQ6wt8o2kU2!N*sW#}u z#*2Xh%;vaBef#uQES_*c2ZQbX$%%7{!g;dmsU;=yy@eD!XKV#@ZGkpkxV>kfEGW5{Q zTm}ipVm}T7vwy}Z1F?IW0p=Wf z;!~K!WWL7=qyZ1D(;leFW>j(Zv5u%H}_S{Q=AdB zXS{!nWVwqBqg(XADxqlA;YB)<17ZgHj>A64LS?8KRl6$`SdQYsy3{7Xo?z=>_=sT@ zOs^Q2m6~8+VpNjW5|vy-MR|Q~d2>ax(Wo`()LLzb|4XXo9M#&y;%@!yu1V9`kGfQU z9M^2>*xj~pca~{O)q<_fdchW%?#is_PO&RZ#SJ+fdreup7A)A^X}YD<7iVS^kvbP= zMn;h?0t;9fmTJ+ZSTrhT*QzVq%F10OW$q1+bl-4S47X%vB-|B|78hRXa+Z~Cxw5Ka zw9Ra88?AV|V#5M+cH3yVqCKO@smp8{E(ac^{WNL5Mu8-wx6r%~W;*Xf>_tFjbf+kz zJ7>!18z6r-P#Iky$=^q){AH%)FAfKoTq>hGMVP5i=E!JqEKVODP)00nk;c*@;fW+; zp)$Htl+nMQ8B3+TIBAU8A69@udXwr5{Ed&r<(*JZS!$II}n& zxepKagw3Q)gV0F&c*6Zc@l3u%#Qh*#H}Y<{-bK&6cOtPahW7oW>rv=`XN&YsX+3Cv zgdMUM!s)ZbhQg1abK+aijZ5`AzW$+Mr0$%wBgVALBl&tV-UE(DU|Vf}4TeSvMUc{S zu;tljKYQ_`k4Rfl!SxwypZp$cKaDHSpBG-8*{8vPYTT775So$H&ke!BD0l<7xa6A= z7`9jRdxONT1k+!Q04NN|pa-XiHf>NUX-tHOD78hcQO|1K;KU@%Fx|f4(@*cvz~N^< z^S5xgb^7+49uBup-y%&M&~(mJl|Qd)DY_1xfJonc)E}YACmAKnt|tU{xjDukgs$! zWg@SMIClAQEJj&k?1Gt&T~Hh{s~^YWsV4D!vS}K}eF5WGhF+MHOGa>X`^Q0G?g>2I zrMz)axQq6lHKQf&;4qAsaN74kthOUH2~?v=>TyQEHr^d87M?Gg4aG?Ij~SVD>S$di zwSQD3wfc_1+*z$`v7u_f>8hC#ZAjOzyu7vI4!v#b4s7g7Oz$rY3_6&)GMJ`)8R6xr%4#@)Ew<&>b6yP~M~cc4jHwZoNUn1oI%{=cH^9!qe z`GtUEbWT38csBmI@64a%w4wkk=uUZxLsOF?9%dR3?TbtGr(4n`=jP;1(!Lw?9KJ__ zIXg4Iz>jCX4-d@QFekTC#PgTo^Iavt2hj>pM&6?+USwD$O za2~m@(U;HvAk7n12Axk^%y6LWG!Q(apQ2oCVR!u`Z^^yw#uh_ph%w6$(!Lm9zg{?W zwkO+@9UWJlzGnyi3H!`s>XIY9mhi|EijW{~#}NCg!~H!cm*+<*kIxUs+sFFFcx6Ax zowxa~!2c;l?e5@M%;FRpudE+W7fbe-={Wa{FLn@1_LvQKyya+DsCVdd@p-mP@#M zkul?c>6=z$RjypH^`f@oiN)X0K8^M!=lAlzgSE7{bHG3Vhs!7Kr6{>8Q1FXhuTHIt zh@w(o?IPd3E0f=`Yq_ad8}{@gPvNg`UVc-SR@7eb;zWpd@N2r5BeB;LU&0+n$*9{M zln^Up>GwkVD(*1P@EbU>v74`#9}V>;%(x|`Ap6}ls=<;`GHH?*DSpWeiTd41(yL*C z_!4~R_@$89^1ULTJAUOw)#OKa=nM5g#PD+Di*erO|3`{(g52qul=4Jnz)Mlf>4g*5`A(cXEv0A33+!azpdGD-6PkJND@$@_~F$;4-e6p6!&o z-QazrILwHBiNHwbd;NWVNuO@1+b{6v*R}Y?z7j(NHO5m($}8<*K))G}`r=IQrq}jW zH{ElsXYAPx1rtkz9U>mRe##@F}nT;b@g&kOOslUlx#Yi>RI_E^@~+lO0l&F<@~ zwl?e^D0G>3#^&gwC#~kzb?!LZK!b_$Cw`ZcGyf@zijc8IbWi>p_iHwZ{{vE>M0cEw zMYQoKF)c|80>;Jo8th}W#vs>NNwvt?Qzy^-eT4JIo<1G-CsLD{!~GZgFvSs1_A%)^ zMoUsiG}eXu80;3cTw}0Wn1Rz5gblaP@$F|KzWlpdtm`b|o@S5o&w~$}MEZTx4l3eT zEMTd8R2!+KU#u|a%SYLx8BOadD%Uk-o{G>Gq#Nwo2>$t^{wjl^s=p}7o*omEZcifb z_?-Kg`G9{Nd=9a1mRS0U8}3l<`nj(tkZ+>j@K#a+bUDi{Wpnx8g4v+CLk+2mZP5R( z%>hUh5uZ)9*JotZ+EY^OwHX=p_SAl5qCP50mk?f*mF417GHXeFXl-U@jU^$$Qj-~_ zPYe%F&`0Oc0~w4T6q>=FD1bcxv{e?>H@(uM~}vo5sE ze;efWOB#bNuwfTR`CcNJxSoZ{wgyvbex}}#6`$q6E0b;Y=8W=^QiEC_ujGGhYIABs z)v@Z(Qge)HL5V&|lN6C;j289y7u+Z8Px(L5em}ncGPF3+74R(|7TSu*tu2wdWC+Uc%hC}%=A^5VTW{&!OfnR zw0e;h_}Q$GG+peEpN+{VNJ+LCV`7Z9ODpO=LnevGG1eeoXm zYaA?mLBC)Ddkw-RVgA%T-&Ehu2W)t+!MEW*^X+%c7`cD2CfPRW`z#0!(x9B2FCk36 z&q6MekXilal`h#fVJG<-PZjXrUuADdIrrpToPHgM`2Au`H!)&z*aj)lULHpg@LzYj zyYbyk_X_Vh#F07hZQozAH-s-&&~dumX6d&-7kZm$d%!BL5WYoZK9j?&VWZgE2pQT@ zK=f=Fz@3q83)iE}0Sf2+4S}2T!u7{xJK(x`fcRc3ygz}prk)ie*%VX12bet+CR>7e zb2bbL0$n*q@mnKB{QpUxeIB0ukX|p5-g_T~=i&Npavk3%!T*w8zX^B>$$aob)ZSY8 z>sN?1z}}pCWv0Cac7=@0nVc~r`n`+rIUR|$n25{qfB%@+{EkWgf7HEqU|ZGsH-66@ zlD93(mgLx$Eo)hpw=8+v@*eU|yd66p@kqSlk>O0o8Dx;1*coI&0wk2AB$UX6(Xwf2 z;R^u@ZyBXPTj-{53$bo~=bU>b%W+8f^8WP;II*tIz4tlmInVq&NGR5El}&_FzUmJh zYs;Lb)-tm1{)h|bkSL;wzKUZKaFt;Jz%|GSA{+}D4RfDi0E$EfAQMi5Pi~I=oqUv? zMp4+4bdXcbBc{tqSH_>s_%mOV4t|ctd7t(gVici(nmeiy2zLRFgXJUiV;$jnaU`mI zrRCR?!l+>GQB#a6Wn;mc!0*Rb7CSWg@Qj;i; zICk~wxN6Qqu9`DK^H|32cn1984EX#R`ozr+G}PQU^L69k^9-{&#`tpr9@qVR4Iso@ zxY~$jq|INh)KCa+{j< z?Lm22fP8AOKWE|lBJ6di5CRPHJvn#EhZf50RR$Gwgw^(ED|H{g2;uYiT5RxnCc<9# zdH~mQf?6uFLwg7ibREORaPl=C=k~!*Btq|SMTz)ESAcBMfC^yKs0A|se9i_^Z`cCB z3*;NNUry~Ki^zg~Q?_5v+RpL2Q)X>R_;V&6%RKmbJFbVNg0mTF4%SD6hDbf#5JUhj z$BpTL-3$uEyppe6hOs4$9JC|~I+lvOCgS*YeS`L-&r-E3~pQ_;V7soFU`F!=PYMZyDiz z!c%|q@DKL&4s?@-q=s7BWu{|YZAUs25;`Z_yN{dVY)=Peb`;dF(uiZzi}Zy{GlS@q znGZDvxhGBT^!Lmu&MPe6_1vKU`WwgVN(wgGrY+l+rd4H;;*bQ5fBvfD)p(pAXE)J} za4#%?{AQ!s%LNXx9xwtit_8)RrK((@FeP9pK|40d3E_ama@~ddH4dH2QCwjc5|G1p zZHr7t0YQO)K-sApRbWa`ioc)88*23nT!ox|?(c-uiPPQS=!l&#-u&&^Zt$}n7|G?W zCkNBp>eg({9XsDvc`{?VV9l92b8}j7Xhvg7VoP3l)V{?z%ZtOqvRl&kGA}0g?5k~> zjEVfk#PV}PsnPMQk@;!W!G5#tNLbn;Lv&4cxHh-RIP;P*Q(w9~)7V)VKgHRc3)m&} z5jur%Lpr-FLsE8>ay{Z&Q3&eWE|Z{u6$6kaQtv;@nxnvqe;^L1;=sQ~U0kic=PyG_$ZQJR&bXNNTFj`9B}$j!&;# z{q*Ks)8dVVbWDj!uGf^WuBu#FrirQ=E~s2x5l;U*ufHTbMzh&fBKGuC8A2p6v9Z!3 z_UqsHulV_%%E~=IU*TUnwYo~=E;i*=+7e55cBQ9x?JV`rT;F5y0O>uuO8B~tOXyM} z4Pk`_144+oF#-V@LwU(4mTMN)iqe`aBgu_2_RCF<6`s?8kNM)%hOdz zq=7WNh`9VU9;AqIxYEFEp-d-y*Hqw7F57=7ymY8Id$2Ov3bc96y{poCuTB)MSk}^$ zz4lUX%f;~$V2vs3PO(L!<0C9Rtt42vq$X;F^CDe^gi%2@Z&LgyZPO$^{qawvAvF>F^}f2ppi;diDb`8uFX$P8+Wi?>ufS--JT z6H&XZ3B=nXnaiu$>g>_go6FkUeB(V9L|ZbnHRXAdMW*UVWs;B5C$)a8GI{&dL$x4n z3et&rJg%Ej{WD)cQjS_G(%D)n24oP{@oPWO9LR9&kjG7)^DS3X#h>s;G57-EZ8cRK zFH@JPdm*OREcaqHGK0bUAS+3Y1Yj9D42^PtZ?nfn3s^<3Thyg z928zKK@$jcq1Dc9VjVGPamX$*@B4V?@9WL3N=Tkgh2?p>xyu2q0nc?5z-&T@_8jN} zElch{-PL(!AT_1`OlQ}b{uC=KUbAuIN>&X1vTD=DRbnsNVVB;nLE> z@9q5C{nM|%J`Ggk)33fd&BxoJ^AdK;AIZgTaCy6Pely;-s(0XE!maPGR%6LktPne& zB)BHTH8KDM#-u5t%7S$nBN>G&$|Km*bc)R-%c6D*5^auL5LUH)DOrlnUp|%>%49Z7 zL-MV^(M?eIj{s*amxIxX>H%M>3xS6uBqbCwzd+|pp^znEY+4Rdm8Xv%ZkiLac@#s( zxAC`s>vh+Az3+Oj&t32Jz3aVxcfD6~*L$URy*J>l_XcCA7YClc(|1rsv0sK49C-HI5>aLhfKlLAAn!+-lHLLLmG#*p=uN7MU348SV*u z(*g>YS>n9GGPmHc2$_qUtD7t7uJTB2DoU2U6HL48Rpyx#G}yzqnJQbtXNna`IvHGs zlLFVUoQ`Z#zY5E3JboiwH)C9kI)UqUz|T#5JnJet8p;y62=^ctN@9t4Evu9yS%6tO z+2RnhiIQxyB0P*nM<(z8<=8Qwe>}_cC}T8m@H~617m1YmPx6ZNmhH8=h{gLm_w4!I zXNil~<_wrx3LqCWW(2m%Q~{o#tTbh4dP`wU{f6?a&H|0){#Q2??2ctzy#3{dT&{DK0#{9f;f>brZy(IAw85mVBJFfi#lUl z9%%@2@p0W8DwgLBEh2Z#v`}Y`B6;K-oZo!N_a#I$(sWf&0)Zzmjkytizro>hj^lZ| zUZ)YO(6V#_D7YO+o%VMW@60##9PeEAV5+rf+ug1yBFIg1P> zeR-kao5AOHmF1dkf2TeL8(-X-TX+1O4b>-B=7%N~FRazEA1ab{($vmv7Budw*?Kw_ z=T~aXN<}CM3Xm~)7#~C^0Kk9>cH&Z<24JA=LZ;H8$nk}O_?2eTXnB>6?Cf}CP2MF{ z{<4C~QHxSve_vD0&b9;)UDOa&Dlx@`g2CR+FHYoSZ+MC>GcG-_IKD26E3J^bwk^-o zLy=UQo!VZJ=C{@@Bq}Z35a%VX+j^-dqW6Wvb!e>n;QHByu}~v%WovtZQN6>_3Z-S8 zS{IHtJy19~xH*kM0p_{6>22)itzB7buMQ1gU6+-$?#d9EICEN6w4$_Ruvp3cTco1S z6u!Mh+J0?M4f1PC24C1yWqZ%z-Y(hEou1ykqXdoZPoNGK4`~cQD9E$RnTx9+@OeMG zFi}W4Pb=jd)XG;ZqT|^IKwxBwBC<44Cr?dDl@|__hO<-DR_cW95wk_(9w?fS1bPcp z3*j+Ub`rfG>xuCFA&%PLdJY|ydn4zA)=AY2Vj}iBNk$DWdhUSn6@gk!etTMJe?b_P zm+*pA7wVfZ_{4_(iz_qW@p!m?L#4WO?Xj|LfLR~AV)MbOp|{U0Nm=#Oda?)0=>2RM zy$aHxhAS+}9N`K`LZcKDXtNf>%~3eJ+R$lDmc+%VRSRTDdSei;@_MhP{USU`oVor^fS$c^>3qS;6V=-Rv!RupIXCdu*|xsU&c3#@Zw;IS zbSp7yLq~W{oDGENW1R4u?Dh}*{W?g|{_LHu!=G$2C zSmHL1a&7!?YXjHz6l`;pd6|fUy8m{wR}=uWAtC@3#0DrHiIb`UjWp6hy9qqrA>+q6 zWTJVEV&^ov$3svN;UrU(+F#2c-9R9m-MWc*Q%g+gz{$|&kMegp8zwJ`AI&Mv7(CV1 zd44o&T9wd+yX6Nr5VrpNczf5ts{9{IT|g zEe=SCa)^XtX(E-pASp9HJjfU*@scZ3ecAV~vG4k(DucbGfyQ8MerEE5D>51VUS^$1 zDij@d)r8yD+OCska)(yydRQcsLPo^))YT!M3|uG3_OXCSKzZUGaE<`NE)Wnx!5|h^ z_~QWK7&weza98??q$;hCs}O-;%o=rOLqnmQLPZ0u!VB;lHys#wfMNQ`hR}%MtmS2J zGls5dC|jNttW)&R-G3!xG_0p4hIEr@i97T;{z$~6p89m z2^j$c7ai2)86nL$QvQP-1*PTKgc3u9?$`h{zc|(`=clYdNzr2SpU3e&GBIs1s%0rM_jbBa2#2IqDWg3k37( zTiOZtms3(X;{f_JaN;%fNcxgtW9g}hg$uV`sA;);UlsYROLR$3wsC2B49I91h%@zf z)@7?}cRpU*I(@K-dd4-WZaCM}QRgxoZ-nf_U;VTa4|RVPQ|Askqj>hO{_}8DlyLJsc5ogHL`-&s-3{*0?$~KuXFxAj- zd?*W{a4?r=ZrT1BRor4QG#8@UEkq6^ryJ*^#+jo@Kmk84+K#W>gghZwE0tg$nG_)n z_^SPtK0>s|5Vw#z7fQA>3NtGSGA(F-pf|-Dlv7^Su0cJ=9;GL^v4W2A_|j zn2Upfe8uch>??LBl;%*#C21T%C&8BH27WSlkF;QcUW@@wIKS~(D=D$E4_Mhl%;oRC zWCFgcV2^^XdGQf&jhyBD;~0||>eU1gAUG+e9f$G2T`zG&3F9$Eki=nd(&4xUV0@z4 zRjmNCaKv=5EfctnJc%^DCr8*cYAyO)wxU?6EM8Ft$2Ti&;6&?^(?gkXIs4jfM3;3X zC$$&x^5LAA4LeUppAk=nH0Q%{S&eCyBJB_P)nLDbLVVK0{fOe6vA0`_z1X z^=R`U^e-{Of`KwQB%AJh*p~S~U{-W~yqpOocWksBbj>z{=h;u$<6tQqH&(vl(mzj= zMc;i%zWGn~;0k*D_V^7rS8&_Yk3*XL(fSm-KtUB03sI?10x(3Yi-1IwxgtFg62(=w zLufT{?*#LCVU!Y31~J}7Vgm(~*C+OtBY=EPFCqPRy_nzWa=mEaP$Qoi7;fG?(riuh5~3ab^^{sjL* zAtH3#&EGJWZ@%f+vl;e13mR^HJ1;*BYAf{5(412z@cZE@LhCU$oz|>^14`E;?N4HH zpk+((fiEIN@Ei~c5Fu!DQkX*`<}VV{dMn#VYN~g37{WWNX+#uc>if>x9&elk2$0j| z4lyiqVuNmvF|qdr@0W36Ud+fX9^VhQ*UgXXfc?U}3G-UmFByWXBs_3bH8;2fU*A^_ zN+epfFCJifd0$6JH7@QOQvkZ(v;9e$x@gtH+@1w8Pqkhzj?Pa|c}B2aZ<7Ccj#_=w zoX}DjA#=Z{3&-mMUaL{&2vpLy%0q?6kiLpa3P-6~KcV^5=MNz0E&Uc*oJ*&J@I$=bR}H2_hc+dEdZe zqv`3Rj}5R-vA=;Ii@I|{LUOu`;34v8`oM`LEvJUfaQj@a-H0jcN=j@m*5kOOeLPNy z7vT%_A=H0D2m}lvXh*UF);B;CFTaV!;t;VMOE#e{0u+xqON{~CCesu(wd`+?k8j`K z!hU6?NUL>*ZAvVQl}O@B6RG<2fd^VJMQBswV=kt=GbypHIFhdgP>E>@#8GGPyr3xp z6__S51Hn5C(&O#z9q7FP4o@gvXHMs>ApkhT|IePb>DJk!ma6~WgBB1&kPj?$=rKGl zJk(<#9~BbV)h#3e(qnK+aWGo>7~EAZ;Pn_CDzfX(=`q~4Pe<{Fj#8Jiu&%r|0EJ#{ zabH2%*rF&l2>c;((O7vwU$GWgLC*Ti{iDxrD=OOd>}dbx^*I2%RkF4=);x5wxnXi~ z^Qj?oZ0-7zrB7@rS#8Rr-N8VR=ofhR!`>U`F;V^V#30GurcoekA;=^M; za2|za(M>xVYBtwK4q2^3`r6GkjXRp6t(6^785$oSO-6KlUWAyWHomf>uyDsK8^>%D zaE>~rHomg6uyE%q8_Da}W18=8W~*EFG{?j=?`grZPZnG^8k~0?gtRsWm*qoc@&HY= z+9N=r48%(skV{D=ez3K7IN}#lJ=#-Bz(*Xw&5VdeRl>YTs*io0{mo0DdiSA%tj=WTp)z}T3hnF==KRn$f1k1fge z4lQfw^heGH>~t6?R;h|tP&1Z^D?QQ`&+n4JRS zyp0VLP3p|3fT_gAW4Y3j9Vm2UM~O6dY;hui`OHH|PNh=_Ke!S#2-n;V_7lwxip!*7 ze|ZRP8JCnK;5d%IKS5|zp>qFV{~(zJ-YizQ2>kU1UbYqpd4~ZKuW_P)noAhagNMMQ z9S@CWHq<0kBnGAQ9&KTN1ri2FMhDnm{bSwM?d$$Vr>F`COG{UVdcdZ_F3Uz>UX<~mtAA`U9 zz@reZMH+cvD(xsLGK;{4q4)q-DMIEAkVz%Dmr0JSeV^i+0K=u>3Jgg zx=ovuIUQLk-Q_V>P&$6GrQ`hS>}8Ez!$q4O>quMG+ng6}jjkHZGB2~}G=-g+{~%XZ zTEfy$s8FWbvT9*uc=>3VWsNdqLrdA}g%KiEqNO!en`aCOj5VvHvvj^EV1Lgc846nU8uGTCQ#KZS^A&i5HP9)n3A}Fm zkL@>j{Ujn@3!g8ZBj3wzm+!@J$Ih4UGXWZUF|C=3p1RPK#+gb`(kSg9rPN!6Mb|%U%c)tEFy_T(*W@~9N_0UWc_0SPwwypv8gW@<8 zVhoN;m4JZKA*!MX*F$tvm_j0UVO+33luz7R07`--q(FjG&JlKnoZ@1=IWMT1kD@m! z_^^8aF;mx}#n$G--KNB@!_C&khq_EuNT8|G1pg1T9a~_mFc~Y1fuy$k+TIos^t*E-{Q`7xjAd$@07&X(z!O9>&xvv-3#n< z^gg@>opm+Y575;vSiwK1$DywFKaeRbrXGZhKOAJCXWq}RI~1y2m=TtQe zuZuPfT!ph);5hFt5ij)I{nZ_3hcm2TVyyB|o)zp8`Nl6j+67YCm$r`iibyH4`6C@1 z_ral;$$qe2mhz_cP3w%&-UsTzn=j)d6xrb6*i69>x9erH|Gi!o^QQHf$yy8bvcvW_ z0qX2bGphwz@C_u&*v9b!-=~+!ew1F83_gE#$&pT@vGd3hb|d=^{FqXiAd@9jB}2B+ z8DBS6Sh%jyNS$T7*gbMXwlXZo80OH+Pz=SL^)lK2gI?BNyS*_crg2*x`v)uef8p`s z)*h3s6N`1(G34p^`mut7bxlUZi0KsDZ`eH{hAgEb#}tO*j37;BOw&BQO!g!6vSwgu zo$O9Dbx*b0W~{)Hvd9#$z_c)hJRMgzR#dpYF@d8%9-pmJ<`@-(-M^Fqd0-U6eS)8% z&>$QnXaOUjnL*^+q=kZ37ds0KarV#vLKm*pI5EU15QU`$XVcw$IEqA^FG8lpFR?^l zE?#@OX5;f4&E`$dZCrA8WzOY@!q%ikD@(NuyAWIyM3jtBKZATRx@b#BYTcn1dn0;Z zJY1XBvv(m1GfHh;mo=3+(qMvPxdQfM9QGs7SucYVFCZv{nGG7z`HY1fF2W2u1htM9 z3?s7;JbGUUTAEUez377+*P27HR(?7aXWKP!GLWNhTFwJ8zgBO=W?_88rs~Bz8zLj? zcPy@*XowSxTdg3)N0)0%$b)*4F3*^d8}366bY2=SsyXu7kYwn!Lp7EySG!qwJlozY z+uxs^-M_y~Qnqg(J9}VX8Nxh->qY_B4X>BsIu*tC^A=B#!1>U1=w)6aPA|if!>ndT zaeA2oQcNqX>}B@Wt3cE}n7r)RlFwv@5+i6}pGmGs3PNiboMRio&o!r(6|Sj`XRn5t zmu z{@JVpS3#DCXhy)$fNEqUAbM zs3)0_9Rqa?UtLxVJXSj5>(>+(tcAx4l%x-Qaca?VkiPP%yvy)sd0a8>`rFzJ+Y$iG>jBpWdpdQnXefjxL3`9 zqwE`VYX`l2ysCeDnf;FDpYDLONi%2|A-A@E~7%s zh3dgy=nX($)|Xv25*j*En$uUN2iHJqLRubpE-yVH1u&Oy?y1^P6IonTXo;-ZP(=^j z+*8-lQ8)W9qOaxFSM(U2I-fq-J?InNP9IN}$WEw;9@CfiXP1pCLPyGS`pY7LHO-h- z@EpibPe`XzZJ=sHHAh_ahAQ%w4b-)@)y@9P*IBCMV+9h;2?AuV<7|q+6>#;wP^<%5 zhE1G+IJ;YrjEHxO(%-p0Enb2KYSt@ER{q`DO#RL~*1!LK)>KVb{KsyqrYk02d(HOY z9CJ0?%V@8p31oH}QHjE#I}v(U8t3?|`MMxZo@??w_E{iqJXA&_lt3p;ffDwrEgcEAS*oyHB)|b;{jI;yhnSa$MB-I02r-Tz zDFh4xg*Prn2x|4NfDsaWl#n~%!-QNK5%jR!#g24ryvvR5?h?zK7^B&n&B;IfJ~uZh zcQb+St*1hIr1l@2B?hKwQRfdz{bQ042u}$8kvGk@%J!wUuMlal(fgSwu!; zOkR`}EMUKoM&-psW<*E@4-4a}$0}=gw8S5|c8xN(kNLzq^olVbkN0xn*pVtce zCul^me=;sX4{bC#g@@?-@4>Cz-0+x$@Zo5@ZBCBjUwjSm(UIX=RI$NN<)`9CNWlZ7 z8RiI}B3>?ag!Ky*)GO=_(mx_6Mjo&B2bbcjht2g{8)K=xR_k6ewsBj1!AMoqC9%q& zh{@6W1E2?QX0KkH7#N$WGLJSGEfbeJ*;sf6Ms@ylOG(m_@#65}Bt=s58Z+7>kX6%9 zVE>^P;;>#ofaFjC$)6|4Jq*S5u}^j!^Ku{bF7J8olKp^pX@ykrChPW<&wv+CfmfboX^^)|765eY zd*}ztw?7B9RaHozAnY}PBuK`VAn~)<4Ne=%k{1$fXqqJ!SFD_4i>^~aAa^I5u9%-0 zF`~dgQD^cG<#j(Z`iRx~)|;n5)phpVhuz>EHq!pXT%LJ}N`)OCC27=egt_nxwhP{o zj#h5D{qO0xSolEs;%C|?t=2bgoB|7;OHNaSAOR8|)k90dc1LXTC1`3yA1PYYY#KlK( zWiqrp@TFK$1L78Muc6pW)W_^EYql+pwMrs$qH|rXR7Esep{>7StH8y!UG+Nhh;13r z)$eR$tHH(es(6W??Etx+k;GS}v(;1v_yDh)9u$;|WBj#5ve^_UBkxSO>^8y?EfFu0ZmXoqZ0SdVbxp$t!>{0gX? zYBegQ2vhAR_H)0DXyx}(t)w3A8#)S%nZ6!^V{V}|nVfJG_@97e5B(4M5xalgf5{5> zox9n$Kun1_m~8{+B&4|*eXLAn^B_YD0AI54AQP{V*V%kpB^)6#hyr4fxiSy#F@L}i zWU*F5QU!2_2?axhkQ5Ff+-rs=n09-<4~{OFwTBes=jLRY(^CzxAweFH-xC=i!_6tC zNny0h1HA9Vo~4a4*R^O+`v`Q}U)g#p9Qk8p{e4 z@rlynn8lVD5L-KDiO%jTjfkpQSAPFbIGj5w5o}%&Uu#xPq1-HEbA?$F{@9kzQ@u$U zhVb;r5Vv)HsTCb*IZHC+;RWq!d7ascN$Q*f8;>MDf@9+90NjT^^SMOu^CQ^ai12M2aGXFik;zH9 zq!6HZXXjvT-boAP@Yt9Td2(V*W^87-Mjjm!9i?#*NakYL%4sR1F!FdxjN%^fwLF&6 z%yZ<6l&~PQij4HL$xAY5ZpQB zLE(YxA(dz~3VoP9C{PkA4b`b!c$dOlYazgvLOCVIVoWr(*p5|e{}=ovZ+S_i z&~{oFS-LzocUeiakZf^@Dp}59*H#~TZPWo;%dRjstZM5YVqdtQ?R*xbEnP~6j1R#ByfJGf}k!PiFHu8?DQ9zNT975fkd^}Y&e**;_? z-&cmtESgw$YnW~o7%|S8n#dt8a)1WW1Yj7@Ne}``Ky(w7P)KzWBu$fDP7zr`A>G6U zL-0v`QFp$J9KQ2S_$>$&6E&v>VS523?En57P__|9(3_1LH(<5)9yogBFRbtnIQ64( z^yn*K^S2pb7ufb=(Dd*)kKJmetLR_iaSkR7Q25876L17*8jYBc5~2|k2+)Wz3>;_J zZxm{R7b4RH$3o87!6>5cd>0(H@3{$0X(YS}4fYScho8_n_XsIL|6Ojv-Lbbv6MByu zxCAnt4%b1MJEh<25}VyYUxYj{F>jeNq7ZaXtu5O;LgQ#i%Eno(ruI=XO?$+)FJP239 z!?oQ7AL(3RHYzX4r8vSv-Ds?;G?o}G`MK$-NhW`#SS<=r>3qDAI6oVc>98qc*6fd@ zdb??n`vsM<(u)028E8Dy{A$s9xe#vmCV%SnJvM}1P zcyoDKeO`K6{&ap?T0Q^`rB6o`jV!6u#3zG|V|`(n=^44DQEZ_iY?nk86TnpJ>c$r~dZ0C;+1c#PJR=&S1Q z6$dJU#O%KC0?m@n;8bIjCl`;`1;=+C^AQ~1Vxoq4!t84w-x|mGS}tqg@=LpYm>t6l z)g$*tsM-ZvW(PWC?m!2cQ~npTblc7K<^@J$MY*xqSoGs2DpBMx1}A9lFj3^3iHa&- zTOX${@6Rb2QYeN?a{9~ladm4gc@?Q9I7e`%jOmqmzt9(tv{q{4Q^3ZxeF=>%y}4`- zKTC9JeEWeV?6%r1^-=loPgMPuS}?ZcKzsZoShJGd*4neA4&f%(E$L|mV=LDHaDksC zb^mg0OgOuD?i_JG;;qP=1f`IXCq;l3B8d+%A2mS&D5Z8I6kUY0+UoA+LSX|BKzkg8 zVqxa4;o1oX@7}Q9?C0X*66q4D(;~yV23Lv3b~~xUUuje@_jUq+K=Mt%e)b6a4b^j3 zcYu)YUBCX1_jU;&P;=xHz<8jM#OgWy*Yf?R>}8E57OrEm+eaYWJ_7e@dap6~0geVh zlkWodlSkNpP%FRR<-lC--MEqc&prJPfS6=A(@U9`2o@2Wd}*GT}XG z5BXuVhuoERXIPk2K-#P=``Zi|t1k~V9vjTOq{(VXDCx~tgy#2_c0$?*eOmWjY2#eP z%l0met3x4cyYje@H57M*{Gv<-7uzWI75Sk0s;(|V6gck9p<8e`;!>g{zz>C(0Y<2% zAa_b+@Q;ClpUDQG$Yp=`vqwH%jSslN;S;gFPb=Z3#M{S^5viAI!!Dj_+qpr7K z<(rhCjnQsEbb%Kb3HgMe7HavvW^V?WP;n4`j|d3-QKFepDg-ZF1!-l>|5>|xBn#a` zrZEyK0^cJtdohqm?iMk=MVn|e_>=dQq+DerStGmG5-#kQ?2Cd4<`UF@^h6fySsyV$ z93?J+bZ+=NLt#g`1ah_1Um;`|fs24~8Po&@gt;@WZXRx~9)l_|De@H!`vF=4P;5oJ z47e-+aMiiB2LTT`@bdKVYA1XMxEg)i?Fr}-i#8-!>CJe0NZqb0|VZQ0V_Usso%9T_Q+5X7-d$1Yub^xQ+IPi{H7<>=vqd-v?TuYaO{V&nQX zt4D_F`s(_6y4u^Co3d-OYZq3QmK5ekW<_SDrzV=>Vi;inGr@d;A z5`E?nMW}?LNNrfKObQvRH(XzCo`BM*g92#+n+l>4JHz<@_1Iob+mCI0I`~692688o zYIVL|Z}w#vf?!-3$fV(0X6VOGJmWUrO_0 ze*#+RvtFQzJ)8A|c^RF1hsq;p@n$MFos*eZa*WorCv$VvqIr(V$p=e8*yVhsYlD@3;ZW zj{m=iS@7lKN$*Od>>e~K=F>PQW??V;8|OIFg9oi34qdWGn^MXNd$=j3oZPgDEq97I zrR@2^@HZ5PYcd-s5_#kRfeR@y@YteAN3xbZ0T!y*!Tw^}mli4f1xP#)fe%qxjrKMXgwXvUq5OZ%uR8)DN8UFruKKMGH-C?`NTqaZc z&-V13=}!SuKwH?AoxQ9$9Od`(c>?ga0C)m*oBfd_stkit6hnKU^Z;B5k~6~v67~Yp zvRQM!g$tJtG>6RbgM`d$QEzrt>y#pKI0{Br!(ORp;R6l!YTz8l6bS8z&$MZfJ-h-8 zC-t7{Y@ak)A9XbyUD|!RH_56j8Z4_{qf)JIDjh6Tl8eD;^U;yl4lOdL+5XFXurjBh z>cB78l<(~`FU+$2$6T4!zpot08VFyYKyV9+CLyS*IY|xKld~ju%qtKX=mMK=ntb2N z)d~RRTudW+P8_r94$rxBegb?>oGo*j{P{GOqXE+Kb8syXR5!yD$%_IBzW;Cdjt00%6@`l!U7TQCyK^}s!%(w@PGk7dCU-d4uVD`Q`leN2>avl zg}4x1I>DBCZO`wHR-~`~=`dM2kSiyD`Ri-AP6!)OaroVB6TjS9bTGO5V8bi#+m>+g zD%aRQ&{eR1!3eFw%af!q;wW677-WU-B6f2J2L&z&kSd`3FL5RT<3D0I8zw<-EBIjG znO)_P&4;>TbC;wA85-6Ue1LQF*w3@p{B%Xio-JMC1HP%{OOi@fmh0FcF4rcQJxbq1 zHP=u@Odlb2luX0?S_H5EjZT5r|HxmD#nlDV5Ts!m)9^J%1GtITFT(73 z5e}mtk#0_bn_PgyBaxyn0IhDWBxdj=iIJmZ7TS@NK z?R3E2kc5!r==onzfzBF0*Rzj7695>RxCjkUcB-uT5YxSX^bH{eMM zprk?2uj8?RJlYrIl0!)WIWZ{`(ZC0vV5AW)64y`c2t1ihYUIujRDhaGgHv3zUcG7s zKJ4F5fT!PKMWpOA@}RAc?wP!Nd6NA(xy_bo6Cob(FEj=M)GK(B`FbHVeUzXE#T6jn z62*yngsP7N%48NHHw?ZU4ZhgyIvbm6@K=fwIRXUtO~3Wl^gsW(2DE?57K3lU0^d$R zap32Zk32GIJGdEiu<5oPu>Vo;{pWGce3UuDV{Ya%JhAGzG;e`Z(w|er5h`uXclhwK zYwR>&+kpIS_G!@fd(>M-Hf0;Lca=cZ)Cl^gI1l9e-zB^2ySRkW>)WjG9qh($KVhE& zy?;hohSZs(IL#1FF}FYNhim^4TnjOpU;BUJ;%(ve%Xm-xjlcd6E^i;wcFfL;5etDD zAEFA>b6`!*&_E7;i6)%S?}Myt7|gKOud(-AtyBoPf9ktGlG|-->{t;ff9r&uAJ2Qf z?B37Uf_30q_IWG2#cCy&f*VI?TDUAi?)iP}$C&0+UpJ5+W-salh!OU4dL1N8fij{XZzeI~J;~KIz?lp(JED{#G(?UVv`iX` zWN%Io@M1U^Xo|VXX0N;4r>SqM zFG=z|;G0&y#8fm|p=X2biPa?0ee3sh1@jVNggUvw9Ge^;O3@UB(T;_{j-D5c2gngK z9JxRrAPV4eVVGzz$673%b*bWF0}eN=2xIsdfFG_^D{^4#J` z`hQL|p3Gh`S<8O8^zuY0O*hUQ2Md>8-Bwnz^=daewfi4+9-buF^vm3wmqx(yys-v@ zsd04Z;L)Ck zlao(2_o7s6U13`?!sLPH=we(~RmYv9x8|Rtdtn;`uB%$awGq#6Qv!L0qpm9A8N_aU zy&GO%i+Ra6{Pn~0YdE1Av0NiCz`W7Ho`v76oo7Etm(?8XO4U)x_v-$_bnQ!JI=XevtA85Fy34Yg4KcD{SDYgmMH36m1vMtx$+2!EyB=tC|Z9@6XRB_`}3&-P2 zJWd(B%)?=g^~38c(Kw;pRm^jr!sC$4oAxCl*SB8*wa9m*nWLr`p&lW3r zoJymDKkFPhtso!OmbCu$ub|Jm-}juYfRRlCFnM$1EEExZUjq9a+yf||Z2tRXcX*%O zt!Y%uc~{UM$*q3?>#du7&)bTq2PY?IzM0LUMg6^q&KN8c{&x0^;m;)Q?D^K|>>(W( zNfhMXLuR)iz(A3kV(cKZDtJPooKobBAt|C8MII3h)gj~n(CqOr>bcFx!8^9AH+$1G z9ZUzKy40wHIDy}AXRsym{Ncl3d_Le3Fp}57b9Vt?VbM5;*lK z3=zwK?%TQ~;IIJfaHq)2uKb?f&uM!57|nLxxmkU^*$w6R@C#k7#96NM)0fFhM~=Yx zy)A|LZPGOJpF8F;e+K*7V#m0m00m@oa1^n@6$4#yX*f<8S4d{&W7#PlMiJ`2pIH@I zc*J`W0YBsgP;h?GL(B~}n+#sz2HTcz$KZ?<5Rl)Lak*u;{!H&+UVvOLfv7TRI5GrGuVPdgB>-TAoJHp03tp%B0--JDi4tPi#^;49nhitI|d&D z(Uj332U5)UeML@b3sNr%@Nh)}e=1_#bDMLrTC)^~K|)IY*twP)FWVYa(QR+L+3 z&+&EYZnzf8!jane@c5A60GU|i=1ORQ#;Lmich{Z}ixU$t;yr}}_fUUHw*S&t_NI-8 zfGO3xVq|~C@>AUgTLYyj?8)oc6rT;~gcoN`#t_{hYykelD^#{!V-@rM2zGUmI4|u8K1Aa^sVVjTfS@0LW zP1D>q$j-!C=m2bILDBJW2YYgS1x^P8wFk)8vFY%(#9#seTm*{52w;oLbW?Cu6=!pT zxvC*x0Q|!mQMs}tI3d`}B`|n_AS;LUw!#7JB@cc3pQ`bO7#FvLDCf7Ymi)-J7E%I; zE087$u6y$RG|B!SXzGPDMOLjYksBdRLBR`z*#(d$4lCtm-@@^FJ59?PNG(!-@VUB^ ze&4R^;jyfqH{RG5ZrA%9R`9uP(7CO3KDUXF9Ot&y`P?Rc$JIe)cQPb?uYrH&#(B@& zfz|@P_pjf(7H;2@7*7`MNkYr-NpHL-NvA!DvB3l`uuTECC*5nf9P}E__Rl>d)cy>j z4?Y9oGLufY%=j71NA_nBeeMBVo;sh$9txjv5!1Dc;P7?7rXR&Q&=+Ux?P5ChJe|xu z-hp%B1+Mm7c+eoI<>Gm>jIt2S zf}5$7C_P*mt%?qi`ieZPHxF)bF^;uH2NjvI`PCiy<-494*l>MA zCY7tL-qviaFHR4L5vA4+HCC=&6bWpj3dEwjng3jjTa6wVsbbp*wG^;RdoPS;6ir-NR{Q9dN^3-MPiDc2vWSOI?PX+B zD_K8*dEit>=gI!$`0mpK$?X=suCOEZ#GXln_r#9Ug*Z2-$Lx;jgjNz)*Ry1*SS?wcR zs-|_8?#x2isf(xXr_LN*$%j`68Vct^BJ%gCbTll;YUjeDYbn*EW@Ut3!#@`DA;oed4@9={=#Pz2X zd`Auc4tx*u9c-iK-tndpzJnq!8@YF2EKZ>b_Tyu|um1om_`a@i)W=1&TOgg_7Wa(5 z1aN)j>BP9bg755@;=~A{2F3ii7xT~H^7GHx^Ye)j>A(4L|F>h@Ic)M!$8-7!#k_sY zJ?C}DbNa*#M+@Ubixa+i3-R#xJj0F^fZ7}-oSwqzr)YjLEx+Z*<;uM0-0xTe-*U7B z&Rqjf!ZR@zpOqurnRtuKmv{={tK;+TbN;$JzK-!?@jHLVzw=Z4PRi+>7`q6+)5g6s zhvw#!e`hxA+gk3O7Q#nM9lqsBWI{Rj*e&Fk!xCwxy^kZX?K+N*Dz0tjtq$Ba7q;bQ zr-OfQEo)&UPIil9C?yr!EiCjoC%eTl-hRX5CPTgp^*v9lcme|1(Re>}n*i4^m<8uU z7>K+r0Vq**btgm4;}^iL_t|IJXFdeGpE$?v{w*+pln>b550EEqZDhV}nmjp4uC={H zrrNghcH|+9ZFQG-%YNXy&z=Ci??M&p#`~c6$%omWybDiO#c$c4>;a#$A>aht0Y04s zzhDQzel`Pg_*ULuiEx}^%~9BiO_RKWi_uCPKu!dKpqzYtU|UaxNQhi-D5VkCfq@z$ zz$iReWu#VFS=lHT3@{2}*tg1tP#nNe8P!MTd{>dZ^1&sor-w3a5oBg`X=hUMvZ^>V zH>jR$5Y~B%u^w0oX}cfN7D_}Bom_NV5E>eWLSS6T!|Q@dN)b)G2L+X7prNXW&aUro zRc{VZC;*{|Qbel4WKth5PY-ujA{2xm#n9fHRMa(uyJ^yBp^hl@qLf;Zy~3dZ{HA$d zTYP-mzUCoooGv{=0?5$dD}mu8ncT9m;Lk&*(pZTkw$zlf>TFBP>0vYM^cMic)T}CO ze5tYV`6Vl#Se-Tr`(D{1(vs69I;~PGRg0bSU?fu52?3;+>qjEj4}sn0&DU(?EWQ$C@zyTY zScWVKixgJiE>lXw;uRu5h6Fzm1bY@=Gm`U2j=HCyc(6nR-jk&1qBAi(Z&b8dNHuXk|#z0Lx zhz<9PkYWtUTYsW=!nsaCI!GW_Hw+bJVlb*9sxXh{5=$RAan%m6oMeiL)~Xd6g-VEg z^IVRlfy4a7zuB>2xo*yxQGrGa{u3CN7qPW!d{uBtZR)3=wjJ+H?r4n5ixhhW=>qjx zkx~-Csa+63k}0hd#XF`1U?`<6UpuvRV`@u|YRc4gtYhdxtbb13vecfSc(nwiE;|6b zy%hF(`y0Co$X%11FQ?+xXY_iw#|;;Jgm?SK)^no?^=y4B9Yn?i~ELya-ap!5Z#LVk6Do+OR6quJZ;6M*IIKOql~ z4UUX`Ecm?RWM6V?W9On9+Bkh_Z+6*(Wo4%;`_B(1Q$ypH;xcfg)>7Vn1Zi)J22?>C zs!QQoy~3Wua-*I|B+TY?f5@Wb*bW#UhkW)ZJ)J@6>9dK(P;PX<+a{XejS-#2 zGsj6okWmM2F;t(NuV6w0C%9#VFgLFS!6(B?ows1U*$pxte}$TNYKR?Gdl0ZISLb*x z2hwQC_Sb=O;f|$Y(uDj7xI&YGizrAO7N_t5z~AqRUoc`g!`WjK@Zhuk@f!R47dt1* zj(>TSynM4I(4dt;?sA~UiMx>dj&S=d2KI9+oI5=+!1XhNfJ>7?R%D72)C)O;6J##L zNP65>bAalF-?=f)l#)7c%X%|B4&h7m3bhz^o<|?L1B1B@z>ECO)i+SAhz}Dvjttn( zoHbjRmx6PL7HKG{DmKuaPMP^KG&ynsNN64}Yk9tT@pG-~u5ZdBr%scb*f$P*dAj-> zNFBZ~2!4h8JOKNA7-KGUbA47i8%POcAQf@}Ag}{XP6&eE)5_l0CVO9f2wX`LgVRaX z9IWP@X4L_UOL@4!ZidB$qHYE~f!Jq!HSFdD!``r3fu6a1bBoFx2M>wm`|Z=X^$j?U zXD)zBWR*hZD%`hG*tZQB1EZDeTNnXPb9fF8B0C`CfH1}wm_qx~)qGDQymA>v*hC10 zav{ndh5ecJ3OP`H?>LoYD*G=;yr}T%u7(JfqJ(WAb~eLR8;l4^7|(#GFW=W%}?Y8 z$g+u___v(@{R9w9eEM)pWaJiwvUua8&Fp_$E^I0$AGojK$%e>=#>S|@M+OpcA5OzQ zRABsJ*oR;!smcLBRfgeNKqC}DN7x{98w7D+fRC3@fB=Y5AJmZ41U$(8bHM)`9pXTU zudeAP1zu0M`;g}T!?l}U-d>Qq`PsG0PZ=XkyDMwPD%9bNCN_h%2IGLq)NiWYv`ANv z0XJVbR38?)FGxO%LX2oHx%FqfUlc?HE^mNN-$Bl8$eB6#N)B?S1TPPVLBL;ehh>k- zH9W~qQjf4>Voj3DSZ)j?Nd?^75fqu(yRWKrO?3>-$fl-dvZBgU6d<+dKpns2k%R#B z4ZB*nbx{P@`Z642aVNTD&UESizs8;fuB{^dnfG2^QlLP95UwPIT!a7tLK3b(xNll0 zr5uIQi{5u@@58oQd(gYm!`AxmuG;DvV!X6F0;eZMH%$>ipwa6fyKaC5Asz?4&$mx#Odz{JGZaL9P( z?`}DDpMw3xt+)CvX1Abj*;*D?OuD`;65!zbMj?KR!ebQb`3d8 z1!TOOmyHF40&)e32Q@noja?HQ1quRBu_HGtGu<2?7afIW+NH2minJ<)#R_;?%r5s> zs=UBGBr&Tvvu4ufj;!478(XWEw`ReSj=jS@tDZj43U_UCcY5>@Yx6j*lPlmdpwa+ndYJsz0{;^)y z^a^u&O`p4NxS8Y+ zBfi>b9`>84&)_!n+(phN)Y9jl(&r?15%KLh#C&OMLh~tN-w27@f&DL2M3~!vims7W zfi-eHf;mI-VtT~bgNMfD#mqr4cgbExFuh`|Q;uR0*W?sOs)S=b*gUQ;6vvAaj`f=$ z#R0F6V+oLt^G95ZV+kMX8)+5p4x*tP4saicG`u^AhWPopARqf>$;Up2dmgrlKK8Z{ zANx+xKaOFZ0nyZZ9UY({#`AaimjOKN3jcRV1F0{pD+teD_c6P--)YKQICVlsh zlD@nz;aKkf9M*|A>L?EX52P=rBpk~>;VBM&%-{c*f|GD8Lu%y|aX5qe@hJbagkzcT zErkg34-&d4>=K@({%@d5#N!H~%a;@(9E30EtSGS7VWNgZTC*secEM;b|B9*B;Wp+ob*-7>%K{iV4~qQRpQcXtfMC zh&VQc;P^nou@V$e90kERnj{>9{%>Kuh@(CjhdfNeG5EEd;*ejzAIJTFfUP2q)_>EF zvN}D#eo;jOPQQpEglHKO_1HgY*;Q`H=rrV2_Gj@p%HJaRSxPf0Dku zFX343|A^=(4AReUNMCM~a4i2gl-IZ)4-oyNIF|W;Ao>Y|^b_~vLH-#D$Fd*C>lL93 z(NCMGpMNL%34`>L(&Z}&&(cr77x8>Qh6nSQ=%-E8xy_<}VqPl=oqOo@AjK>@`&XCo+)2by<3CR3PE63;iQ@RPgrnwQ0>zOKjN@_u2a=WN#?3(p4lGZw zRnJX^f$=!wTQ;|aTlbz z1KdmFbYm~7TS0WSSgiXzsrwLmt|NOWJ>v62ATVdHkYA$k_RJX=|%eeV3t$T&m z#XQ^-6rEebaXEkk_3@E$wvOPywvON+HesBtqj=gRJbhsMxbcqm`AJ{q09_|&+ z%67;;k?>$m_(5zdVCxW1WM$kDkscW4;Mlokc^aa3nMjYD=vWEI#!9-s__DM|S#vsc zJ>Wt1cs-GWGO_)q$MvyF2q$@Y0(+DLvb+4V#Xim!+o64VR>Cufdx*@9a9>)3`$FVn zM!+7AlMjlgRl?H;w!(f9Pk+cejY@d>zz_(heGV74{}<2i6c%zwD`G658ie~HqH=XOp34FBUXU~f z;pbcwskR^qDpceGyjvX!HP8S*$By8+cKb!{4*UGM(~WhtM>~$; z`Y&^G=0iSytbXlS{V`87^I@RAY=>0;R$Tva;dSN>@aOB*HwD#y1J_?*w~sX0=gsLg z*4G^E7{c!eUq$VI#K)s|FXrwC;7LH=9oBPE>>a!&#=;i)d&w%f2%lLXWm%k@-N(nH zvSNQfDJ#Z#t+D$N+J#ry`QQW8A2o>cDr1zqj03g!BEy2@B%QrwP+h^(;7uTe5Zv7@ zxVyVu+&#Fvdmw0VcL?t8?sjo^cjsO%5_I!CwYycj_3r<}JHMXknmXsx^qHE|H8b5( zXe68TI?8ai&_p5DK}siC(^vYRkI_$ozF~Pn60`|CUF{JQ#q8f_SK}N-5i3 zUY8c1MaO`TmOA*0;ug0jX<*wKdYkl8lxGFuO&^XIChuknR=`Lsn0&m$Nusb}1b$xB zA7#V{IV*U8IGmP)iyo5zjbK2FyB*oMKcem%@_rr~4<&<$@Z0SrDuI-)AnUUrh^#*; zI&;c=2Zks-(qqliS{SUIy|b9Z4c z*}_*Ubx>7!z>t0Y5lkQKLOJUEKAdhuikvBFsCXMl#vWxJ>D2`1yvy}%a0oRQ+;{X5 z%}?)(eHug%gI@iEcr{v3epnKq?Uf&#@JnLs)()nDnGKaX3&~l)gEub8DkL1^L{)@tf{N%o|enF#iG z+3=dC(xNi8(k#uxGuovyfm1!4XU)?L!wL+cq2ed+iqg&^Gau{oXF9G98+orpjY?Ui zuP91QHce-ddjmQUS--^C_W~M{Fq&dpwb{}>3@hgJjqDs_7Be&M8OAXNT&w8@e8lCd z;~?khQww4ZdB>uX3$tl^{8bwo!*cQb_W>^I%D?-M4b2N}L zr%SZGqqOW?JW5{>#`vR7c5aSn4}C=T6%36wvoD&n`h|i;J}x|5d>tzfHq7U#dN~IB zC$C@(T60>nFQJ})%;Q-p@V4;~9MM69IH2_IFMiKZ`(IZ+W57_UOSnC0W9t;aD~HYq zu*l9bbaj%j1@{?Za*cc=*bDIb3EVS!+Zk6H3oD#@s-Z~~;(cVZp7^qDHse%#Fck}@ zBF@W&u`keN4-2E!qtkC#(Z@yen|2r7%*!uoh+B?YtdDlg8j-LfENluIQJje)jRnH+ zr5O~n1&NbQ&FA6zSBOfN}O{bgmgLZDZEdqW%Rb?{|w%(jn}oxY&X?yfIFr<{v_ zZC$w=;ou3npczxV?8v0)fbW1N-@`Y(Gajk^)E!daFFYcJtxWMkq=Y~U(&>5@SMuo+ zDb=ViE^z7z4oMpi#3kbiX<4Q-ExL%-UbfVR<hZgJ&RzP>QNLWsVBfTXmKPV|^c0-)V7Ig{!M7S=Lm0%UsM3h&zP4uxif|{9B=M zcof8F^$}^vypraO@SZm$59kj+!IDhV52R68@BhFJx5r)M7`B7{If6m+3$eRGE5`Fk z|HGUrV{!p^)xTyW%Z;_>brR9GgH5rPqXJN3W%3Ov$XEEhF9lb;$cv5Sr0maQ=V)S{ zi)C0LdQ1h6o#b6;#WnM8_WW%EG1Q!BE0wZXn|g~gnTqt(`GIX>$jzx;KYSLMEwR5`KiWdcr1X|g->sB`M9gLSZUyHlK+(4te4 zl3ck8G-XCF(=%LCD~uMvBFf@^S>{zwT}V`fNVe zpf7`1`jZU6=LO?Q=+W3l-H=E|r=~6=(PKp@3@_Q!RNl?^IT) zJj)5?lZ~MKx(jM_Db;QNuDew;a&10UHDTa)C4QM|rseX-x4inDF+(V+cmzzGMgZ&2 zakSbq(q$eHQO)jS@`9^H@gX5>d-7t>(@h5%L8$$}y`R`JM;4ZPb|*Tj4l8ERGs<}0%}oUfT%q@9-=tnaRgPmX-4 z>r!!VqT$8jS$6Xo#v*o%YI%JbNu1Is$^3!8<8)tB_9(KmgION=?5n&pE7$Mvh*V`j za8@+Nx2R9Zkjs}B@S_K_u#=N_E2?wT$=6M$1qANCtpQzX741(bPw!#Op9W6!;NuiY zJ3W(a$#goga2A>p5C?40k>rJ9C#7ms_V_(POx#0-QHB{vy!VUpjcG!xs}|K+-Nz%p zy>T3EK%X9aQhO4Z_I@n%h*1x_%jYdDxbFiiN?@{%Ikh*CjSS6kh}|&<6WO>53q+m} zZHS5&119eRXNVG}B3l|?-aL*0d*fE@8xR;}sd{Np%Yy94TKbAl)T~=6=$IG~^Pg;=Q9YTHj#rX;1I$yZv zU$5@hUKTz7+Gj@&?H`gHf&}ESW%TUuLH_&$4&G`H!%Fq93b@N;euG3b z4P(M(KhQ2e6Bdv2e%d#%9rJi5w)A}W`+fG9bA&FPC$8DCx#IK+J3J`T z>BG^F1Sx4B4|HBsTM;kno)d~yY0Rrd1jc#(0*`y z){chpF!6--Cj1t<{wj()n$i%^gk2@kV3bk%&&iESwP%u8o^|HUN|7G;9)Z%LUyEoB zRGto#ldoS$s2Cq-WYKh}3qP_eV`+DFZR&V^MMv;Kef$usL#WXG;id25rfvf8l3x-` zNg6OkFDy{oA0V?U2Wz#6sAr;MrC?$Rm7nKUq}FMxXGY8ERYYV5M`dTwOJ4-M_kRWO zm!;`B0k!R3w`|(QLoI5v*SPt*i^ZP4O|Mgv!dqKSchl*weIW^!CwAX-!+yHqIZyWv zC)r3G?fdLN-b(L7EF;b{XXUy4oQ4?4#c*eVI7bEuThS4n&TuQ9v)BE> zhLksxzAZ@AT;pbIDi{H`Ad1@>HCQ=?8UN|`Pn^Y{)U#n066}3;EGP`n6Mb}bXm+st zeN1&Ygiz8>xxhiV$D0k;i7Eb8$BhQ-w{xtCGzLSK!0YUcx9$c0Qh-BwWi=f$Ez>0T z1v&){3+S|X%;cPk#*FR3xLse1b`5d`M;4CO^{W#a}q}JVHUaLx=r& zNOTzQR}w9{SfdB@qPTssBL8lT=drf%5G3#M=t9Z!c zc4$zS%-Y!zoC~(aqQ5`s>WiS~;EIHWHp0|L3jU!T$2E;irA4>bJf(zB9Mk2C=f>}q z#9VCbz0CxMlKpw{$GK ze0?EJ-qd)Yf0w?*5Pi0aO+)kN&_4Wf>J&AIil+h{WyH2!XS8*9$&T{}v|22or;J8~DI{?eSkM#u398KW-m^|1KkK^u7%o}jrEaf_(7P~$#mXF_Q z5-;HzqL!K{_2f9e>cDLYS8@b-CM4jOTo1Yj0o5#S!WZv{N> zC-KHS#ZsR_230rf2aJB*(tJV~D?L#d-})soK(B}l%3oL`b%GFZreq_E1Q<&BG*GQo zDTr!d+_(X5DVML2aGPaicH+NW-UnpoEhz6 z_JpEk;x8F7?Q4J*J4v*SfEC!{|}l|$nj!c<(M?8}DL zuCjL4EF{EG2EZK@v2!K|9mHbGbG@n}hGq`Las5^w8&GG2VW6yJ1|Ptp5pyX?`c(*v=SUB+Lwttc>2Qp>o}s`j^qQmej3}X2eb?P=FgbeNp7$ag z%(*yEq}m9y;)n}-LQaWL8|$dvm=N5WN1yOzV-HORdtt9x>GLtWA+_qN;1E(SD)ArJ zyI$i!(gDFwr`@_D%yCo6#s`dU^rcF{*}H{}aTX0-FsvUeqSN>w2E*yk&K zi$F{M1te^FOd1_7O-XO3ES$w3m}>o;37nURSkBdQn7Yp_EJ5mS>+rvq7hkwsczj^c z)olhVt4UAn9W6CjDGa2+$?hnTg}x-r;w^|xS~C-DTz?Y9TqYrL!jl;uoAOma`_bFan6@8>dVXGOF@&3)87dYJtCN@EN~^9f_4`ebg}A9!1K&yIK{ zHp6q{3$e8oTCZH)73?cQ?L&P|zY6oFc?32R)_koTthGc7wih%aOg;a+JBr&&?zRkg z`Nf3sJkHI>6hk5+HAdoF4nwd_vc;Xu%*^;VAM4{sehRaL-v*c@l3J1b)Otw#37i0a zA+1PzDM1p1GsL@f_fQ^iMU0smW%ktgZ6MscthwqLM6$@@*S+5|f$_xO|2dirdJt50 z=~x{&J9|L1sw^cJwq-AxAkAdr<2&o?b!=Q%;152$lbOm@8b7@Zjl!g_*QKb}-wWV$ z9UBPqr7Q>?Rf3ql_f)Wj#k)`14@qv(hfDU{5*gmIX~u`&s!4E15M&{WcjsP#61*VMZGFf`GDl5y@UptGQG|-asbgGu8)f@$nsb)YS}pt?W$? zkiu=t6)x^N+q}yHWl7M$gs$KzT2rS_S2L9_E6-nu6x~9TCl<9iR!Rz$R$iO)@8Sa2hpz00 zjn*b`9P2~Ldl%%oM8F`xyO_KF__m`2QgO|T;KF~swlF0;-NujIG4D&mYaBM0k{=nD zN>5~e!S~JAmgw0^Z)IxhI<@P`O5WQ+H=sibYk0J+v?fn?Q!lA9YVve_;U;5WSu(S0 z=wbKn0%1%a?xGsAhlfQ*xsu|#&J`iVIu5}=|1}4;g;W)V=D%b{OfYQC7t;>_;m(#X15v1%be5PnGi4m25pFjdc+w}G z`Y@xQ*4x`AT+q!MLC@VV&6QB&+n?=vWY7%>jnprF7+QD=e!(+3)0A5M zxJC$m6v}_~KGkiCzxua&RVdz+?y+wTeJS?gG-it~{nY(!WJGy9N+lMLWEmBCE`$ef zZQot|@%`;#G|=;f=8-TELYX~)O$MXR_l$Y|WUd*FvmWP!5)Xn~+kh89hK-Ct<+A&< zIaX&(r$ic-`s&HT{^vMufR6`~d)qtEd6RGco+-?BGw|>4?A{tWVHTN?xdBzzDj)??*VF+y-itA?@6U?5_^>D(TgIbd0V2+ zT3z>e^-@RHC2vX!FHk|hOR+q6td&z^&+exkZSDsJo|&P!hF8|JDBeS4!6(CO4&HPv zrCubvBNj}a;LJJsw#Z`7EKt#hnJyt_IB7gUFo++2R^Ze@BI=_lJQn*rNaw`;ah6Dq_d=)Xw5cvD z{Ne`HBj8U+%hkyY3QHF%%02C2PWNffW4_1y96vo-fTaLJVpRSK%)4$lu1_v?bi!b{ z_pQ=E`%_z3RYN-`wdq?!Sn%I!?@QXA{MA#Ls9gQDO%&p%wRCo&0$ez}n@d?6HS&mdHbYKT%wz!DNq0AN5;*{35Rs z_((x~hMM-f|18{8CoDmf)yJd((@hZ7PJvK-Zj-FtnP*=(NF5`7>;q*YP~xZSD}W_4 z=4=fw1c&mlnv&r!C27rf=_=f>@!QgtXI}_GN%aKzD+bHSg4WK~XNlu$F@~)x>nyEB zUVq3;J-f#9@0*&EZSE%NG}npNAR=LvB%?JXo@Z`5zhla_$;D@2ni6 z+@_!gh-DRitB_sx48ymLtjYVZBHmZmYv+#RcMts`h>pRGdQ-c;MHG%rQmjCQIz-ZswLHxl<4 zh;>@MU#U0uy3qoE0fAX9<0r<2Qs%mf8eC*uM_9F&>^ulkUeMVDN8Hl3YNRjnA0)Cy zi#++jY6~uAk83nor*5!Gm+edS!iIxcg!7A!9_ zQ$NLtyBjucaIR%Q5Bt+C#)Xd?;@~d~j8$nPYRX{S^SoYZ>2Kn2k+aV82iQJ1*Qz)pGIF48o=eiEBnpm{50Wq*FNq4Etu z!B=N3S%0Z;MxWM5$Tw5+slnY>$pI8BzVI!roq6O8GF;u>SaKbP-AvW!>=4BK`|oI$ zqpb`5)WD$2OA!_4*30wVqU=*mAq)Hrmg(f>)FA+TOc<8CZGQTe)2q_^jn0TZSKOzs zS5ct1N3n|@WYqWhxG2bD)pW=2doI_z^12$C5MKsKe^tpz;bX@stuM|NeaTUw>fh&P zWZmnpbSE)EF01X^3KLuXM{6d$LY00P=-SYG@Y&)$EiqKH3QBb0yXiE0eKyT8Vs;4q z{ec8OjUDd;;af~`J-mFOENBy*aXj(+H$~2J(OjN0`%nYX^GEqWfWPRw1)I*Wx60`% zXkX@vCPc|3GUHvulH8N21s!y+k?Bw>dJikIwvn(VA{`|jSm|~oyj?8OtMf4R-}AL& zZ%_$G*qIRXks%3vyPd9>Up#^f$AVGQ4^eU9QO>31*si46?BQx(4&ZMbFufm%_lOYp ziF9T#eC$j8-!#fzXTd71zb5`+B@8j#81Bi17FEUkoW$4<3F;gfSFzGN^+(Ki zkyzF)s_nEgnt^lHq$9zaa5jnyBArg;`igjV!Bk%>P8!i^%7RY3h+^X=B+SuTVd%js2fSECF^&e^Y%|RcnQ5B~sJ67JTb>kum z>v8%5xwWjyTD?)Q5_5NbdsY6gQGX;TQ)EP3qSbXs1a|f?{yExz)7r13KC-p`YYLle z0o%{_H?=6KQkZq&`S?c;mptE=zdI+R5t04}e|gu5O`ZB~`e0H-o-PWoiz*@Bynr;k zFbphGvwOr28aFLN6fTJR}D(GB!r6PS((67w!yhl?U%!&49@`cQ5}DA zQmUtFPxr5wJ+g_wR@26z4Z@xv{~X3n;|%8La_d6TKVQ12S*`MapB1 zvUlkLP;b7iVIAEj?rhZzIeE}QJYEocqE+sQXXMBmm4i(dM9n_ld0F(JM8G%07jc>? zyKP$fM7$JI13)!^M+Ot~pZV&4ZFU}_kza3%Y^f(-97%K`r{PxVHpHq}@eQ%KTqr)8 zvwAypSEvN7eGP2{CS%oI0Ck3mPCEHw)LlaN)V#`NtaB5xVlr`uQsm1S<|g+j{d z(44384k+TZeJ%wGK<|N1xl};JG?n=33-v9}DNX|As?R}H2f)>kKtK=~7aGHjyW;#h z(3JSl72JTjV7%!1F@kkzux?Pu_1GS4FDvEy?A|q)PCZmAZ)VbJ#osWphRl{n#^PJP zISHSVWqZOe-}5yG1uc-4c8BI1wC3ysFz&%Hj*pr6YX2)41F!JNpoJ9gMHtG@iNGs6 zCRs@dLlk!;ZwpMLz5C}ghLWo?Oo)SC{AW3nd5(}D-@?TN@D4io-MEu;EIj1~)0Afd zpoM?p)Q%Kd)&{`M5c^s14QsO2CuRJd%6s(B^R{e(BKA_+Glo>|rCUm9cG5WZ~Q&pE??>fy`nuV~%(!nWM5Ip7t5j0l~8CSUfvK1Bswwnbxo ztb@pjUv7w)_d-9WKy1@;Xu8U$2l%|IZV4jdKM*(<>&5vFEB5_R5(_EJBFdEijAszP zOvh*#ODA?0)zY`HdKMHvuXwL3G_6)Fc@E{PZslT1>tIG$)Y9--l%o>qjJ?W@aGbJi z+iFhHIZbkzN=kQY>PDKTWPIxOWc?EyUq73$CCW?*sIY$>R696!!;Q2Cv^n4=e3b6B z3tINyWoaZe{tQr98)WLfQ97Kfv*0b=4!X~rWom3UG_5&r+8W`@0d~n~P`3o@R=2cv zHaa%8FgFRI!0A$1mkh6K2(B9DVe_VH|E1^DY*5i}AD_P}#ZWi9W@*xOePA^((B;O- zR#O*#BMvT)j%Y&7pY_I_m|*EeJ>N9&VDV>Wx_BDYkmw;~{*pl6nqItFF>fcHb(G+d z6f73pmM&hz##bMt#p0RO* zd&QBcLuSf4W|D!BBQtjyj>g~GKugVp{%|*oxU`$6h9#~C{pFoV;K$GG_A)ktB=T?5 zP5+KzJN?ASZm5oyq||*RSUPv&K@=kpQ1)(JCxHK6aaFk7KYk`U{PhXe%kJkl~31+~+08pbyU2^HL03TnvSzY>mQ6z>VH`5AQp-8rg zkWuNMQ{RMM4XB*0Xu_{nw4Kdt!md`hnC)mHu2v$L4QoQP2V~8bG~wAR>dl(1CuWW- z5Q7urUNQfWHY-Q86jWOitf#gVURlF^Qwu4;q=?$*2rW^iS13GNlwvQ-;j^N?lF3<= zZ2Xr=dd@CW+|`=+3eY)Q(?oEk=&PJqQxbLhgD>PdU+v75FFCfj@RYD4nCaMtFLAr* z*D2+5LO_A(DFZk0;nz;v-eyAh-}-Gq>s`pT6BnT8u1}6*1fY>Fct>Cs z=(r13sYLjUb2~9>ZHoAzA?{zQW71Zqh}QjTZ-VVqp`ti1{_R}PT^4B`;J>Y;X*Dmp zRxn5Iw7r|)Rv&v?4!;-m%~;Ona3fDY|C|wo+aHj3YnMCd>P>tz*?C*jMQ}6i>y+5p z9`4IKeAgcL!aIfFMP_-*M7+yz;uSAcJmaO*k$k7WOP=P1#(YfGm7E4L?Bc!|d;te^ z36u1}fkh#F{vwWZ8xZ7fCC6D`KNgaKaImo-4@ti?SjCTnWN;Mh>?e@dM+27iW6K*T z1zY>^8BAN=X82*}O`Y7f`w{2O;M|7#p&3o4-4^@d8BJ^5rubpyjB4F+`Y{@fuG}H{ zQS1zH-!b~p?~JtG5&6;V413-Q`Z4c}KHkB&VGEC;fCgW`3IpRn2d|%n$CW?}uZY4E zGoZUy=-x4A(8TMvUSKWg;`K}KxFcxe6}flf2K4g!DR7JgH2Ml32+RYWyut>K8-Z3{ zkpd@nK##95A7jFxnOB4lU@z$A74Bm^5VZ4(@)7ru0<5MlP^DVhPsGQgX;!7VpC^rB zGt4v#1|-WiWHT_+kNs{)tYWAft7yoqVzM2}Y)GwQycp|f$gN@~7z=Aiuw%#?D{08E zW6~QlTT{&(W+VpvR(eH`|I;KR(~?+iPOzrgl5}Mb2QM#CfQ})*&n8(SR|!Zuo2Ob}e+EFa+Lq&C0tn^I9h+vj)W+u{* zm?XNU23CzPNH$AgNTq5}PaQXGXuYI(0R}Ym5|Y9JMP2F$$-{xhE^UNl(m)lLCPIo) zptDO?HYp8I)} zeTo&JyG!>bDK}8TrE!zI6=?6$xk=^;G;nF%q<94SyYvc>q5#FgbpqsZKvQs=0GSd{ z4csI^F#~i3cXg361LeUDUF5YuTX07gnIljS+|osH1M~&=_>qzTrNQ-nCR}Nw=(DME@)uHJ&WW{v8ByD zr{K=MrQbR`-cig|sV8`@k@w8`N7Q~U-l16Uf~%w2p>*Q{8GkuKinAnj#QnG8l4efH zLbHOURj0=(U`vI+S>DoG%(H;tj5?><^;EMXhIqN%jeScjZZ-%)N>p-pO6Q~QxomK1 z*rDWE-09A}l@qWa$WgwvUf7*E|JSYQ!MeA^J&37j;S9j{tEW)@RDv&ysqo;`j4$+h zHX7MV)0MBx*TxV*cQKJ^ez-#-?VN2({&Csg&1g&MaRmk)^S-6qS>wBxWW%n?3TY-_JtUBE8VQXK}7v!NS37`D*gbH z6&i@Fzg*tG`;0pNig_zI5J`Voqkj?cHT)HfR=6Pw{_;D^o)80nrJWTNi1?d~@Ujv_ z?F}Hj!VHmrlj~h}gy_8~_O6gXq~Bx%YiyL7nwOFr&W?{QP}t1a2rJ=HD1E{0b_(-F z^qVl{(sa3QWm(4kqVr z_KD1Mtj(VAl;xdU>;~1R_UlDW zib;^*XKQ5BewlXTjz%p6X(GsxTDcu{#+AZj+j^p4u?aAxzA%5v+hD|b*M?m!slKqH zS|D5_0~}SkwK$Xcd^P>7WBKNxCTv^6l|?v-_51JUk3hLeh{ER-ENXMPCusv#d{%K(UJr_E##Idbg1B#p$p4@-buKijoZ2U31$8w z)0_@xN?@{r!K}U^9=~br*%(Rqhn~d%7rfBVJ*fVjbPP?L4_k^5)*Uq!wGV6@wQ?%I6y<832 z=Cu|8E^XQvEdXjY3uOLp8D{xA$*vUUomg?5uy|r&31~^%Kiu<61D)pyB@3tzw%2?7 zTvRH$qPLnoY(2(vkL1cLgwyn_jLz+2N)U7MyQ*3Wg(nG+mF*WCSHNtuw>V^^8CG$@UTul zYc~yc+|B?EPjeRklz#Qc61HJ8r1c72O+3{jvpHhb;`;N@hj_M!_{npLf<(sgM7O^W zEu+PM-?J-~@sc~&kr`7*zZk(y9GugBFq3GW&|z%tW*?NWZrP3TYLy@A7jNFuWjG9N z%Am0QD6MVBJCpK>H!MOqlSW=bAlHlk7pf9ZR4ReBC^S0DZP4@oV07zf@PCQx|9mp) zaeUYJ_@5Yf{Ll11{$~as|05`UD1D=`CkX%4|APUP|A=GI4s;DPM>wo6!>;ETyesQ;wyVC!~-hXCv*VG7XYy=+O z9sLK&l@{yM{|&YuLJ#atuw#GguHG%<)Bn|Ve)^9bywuZ&Y95VBO}0a6}cL@4ZLS!aLr<=xA8>CO%?gTj+&Ar&8EVGE8X zHij=BcJLgXYNb_b zY?lZA?|JeiUepYMEd-H*f_m$HM74!Gg&A@PF5kWe9OM>*QO1CdfBndoY->PI1~6w; zZxZ>h6C4|QS-SIT@1N9r*0WKbZ5l)8f6(PkA62rQ`OR~t(6)Z@kMe0za zQ+u$nZVVA(xGGFG7S0jR%rYz{;}o!2TO`LyW29)5XXA1UYXP&wyzS{ib$yL56TA5y z#=$5nV)_4;K%#&e)r~BMqNH}Jvm$F>FUE7<)Z>K=Ku2l%wKXoC*7HH8wP&5r^PySE zDhE{xiHyYrNmuZjgSff4Gn~MKXt%enP1>l=a6qTBo_DmlV))gO*xGfB!M~FpI!4(| zzUFD8;o%RsFS7y+4N(ddGcl8hQogF)M}{;C1gS8Mgz21L2pnUe&-IAzb^poevMrH8 zt$)$XJy9$dAECWlG?7)f=^vuP4SAk*nST;}C2iu?-A=K>wF}Qny=3T^&4Tha8Ch0% zf4chb_^M@s_yoVcLtVCl9)$vTi~!>6J; zr`y^cv1uuvyE*oHJ;d5HGn>c1N_U5gjT>X*-Pgm6r#Yo``H7O}yy>Grp&nomdw+?~J~UFJ!Y!LtxXvKWyO+KZ(wG#PptwvG<~S@H z`2lGq+e`lo-#F@KIIIu%pnlPhWzN-J$-|yGxs|*ef-dyPu5&Iqo5w;Q<+|$OGj+@pM^85PW~N}HGo2?rU?U?jQxyWz{ADmQlPfWovM^T^%T9yUNv;Je z^h}`qr8WLbCEvi%dlXkSR`Hq=*g(ysla>ZH;xbcfG1K!f(|Rz=gLC;VJwNTC9Uoy< zbe4A37FAgmOtiB16QkTIA0E$XFv{);wU6jC>u}k6knn^z`T-Wr2MkzB0ZnFSMp|`xqHv{tjWg94{Z%~9##896kqyXwrU;o=4Q2*@p bzsi5T0ksBx|1Zly4c($K{g<8#Zq)l9&1W3y)*~0X7081D_%UAO(gB2gD@|fi7DI zg^>c*Zo7IxBy`@kWxG`IfRP%!;gHvL-pqF|qy?;ibMh>=!>qJ>KWp~?|NsAICyO!M z{Q>s?D&m|=TdsmU7ok>omT}YExUKLhGl#6Q;E;qWHzEr3IfpGN_BE2nAEaS>jJ1z- z$HFHrE~+P2Kr@5Pn8-*^B;%N?DOi#D9K1Mnr|R_ebwX@{tXo-GUFJkZ;YS?*)|)sg zHd}mgSwU#T;Sr1dv7P1mCdU}eO=C5gJA$Y3iGSML%KpabAH0PdTh1g44ndNY5d_IR zMJ1ODGTGtw>UFDiLOYiOn?cKZ|}WTGPXgls4-wLQc^Hb(f|xBjK(?-`>wqxFRHz}|NDk$bN5fW8LYJz zX)C|n`O))k-=UP{-bJ4%(uO2*Ru0B1HmGq{bz7Eq4>Wq_+P)xqyx$~0}NG)?-9Y!h-63z2mXkr5Lmy8n*qz&u0F6LHA(DG&f~ zG`G9Fid$@CD3MfV@?)Zi>h$}$>r_G_R1L*K8EeEuXj8u1%)Z)_S>n3Hz`UD&h6u8|s;{jy)RiK&i2ENKK4TN!USQ5trb*%+60iyI#?X~A`)iCJ zb6PLSmL0z*+0A4YPagmdH)2~(L*&44A+g`Zxi;59+;$1OK#+9)x4+M%-My6f5C+0c zZb4_anbY+c4+Ee80#0=%#egX<^TRL$udn@VNAZO&*!Hh%Y3aFf_Y_^CQ3yx(I0?dH&tFYvW?$D=PGRrUiwe61 z6AmcAfVuxGRqI;SU_+o}`%(6!AWh_KbU0iXZ@4xqLH!dj5j%%kMlee#SqF2@>2O!IeVn?)hK#N9ODgi`cvU$E?>P z1Oz3r60+XQ0(yr(SAV#AMY+;_jkiiw5GgH?K+5@DMf7?2=|3h2*$pSW`#iX z#>fF5{*w%8ybLCGGx6DdRLmZzO7;*jnbY)DU>b5yqM(CXX%$lmfQ5kqNdsv2fBRbj z?1S(FGmM_d_l4*|p6IVw`lkS~6{sKuD@36RQ@A1&DUNuGQnX?et2l8LuLLDZ_?TS2 zxUU>YB|SM&r5XSPfgw;B9DzikF<2a)KqQeVR2rSZV0rlsk`U21Ff=mujX3>Lf#R)Ilua13$e1lN#AUT_aZh-5c)Rg#*8`dz0%jaQUA!&? zAX_4FN&F@?5=Dl=tO5tF&MR@N%ml`CldRl1*eq z)@T*hXi}R>Q0kvlTH3~Cvp=`SHvYD8=BBl=ikd@6MoJ>cifqX#IVTTduVEizL&k-V ziyn{C8dP{iS%_j$yp4mkvvxo2fn`)?Wm`Uq^ThcPN~U>L?rnEOIW`6yo{Zl-XDOtL z9!7y&{iQ5@8Om74#Z}rB%T`>{`LG%bagz(cPaVIHUt(~Kj~THfRyWQAY>MH{#%RX3 zTr0L_tF$KTu;~P+0WDClO!m7LyEVS?_r^QG4kA7wgeTvS6C8Z(DD@l19H92abB34r zeeCurfPX4|&(m7Z1yCQ08*DfrX#R}dO!*K;)IaMt+7AHLr&@5a-OvtgUu?(gkf+=G z+r#Z90AJN@7RENlX*%XC%=z0mCq?2|9E<|!>Q62KvUTDYbIAr}ELo|{SXSIAl{y08 zlXV+QV``xGk#xz90qIUDLNXJ8k6(icx_8}J*VmQRjD%Jb#ZN?$;+s`x)l!A4nhLHM z;?1o>g^KV+KY(y^inpO&Cf~b?wcA47ZU;Iu+CfIlLBr z6Mun^4Luga*Y8vCuDp!RnRi$dx@K9IOE|J8NNU9E))TmQ3b*WoDJf=>) z>Qlc4G^in-(x6$*Xnq}e)j=8!dMrc1XTz54VUFxcKOS2QvO4Gj;UfKZ_##f?gozGMBR zY(~{=bIrG)R-?A1@$3IUa&Ul{hT&<{qVW4MZVrF3t4)MAaEtn>)kUHO4Bh~wXps_$f zKiLyKofJ8U+@p|;pN49%B><}DBxRHMK4=shP{}Wvs|EoR7xM>G60DEgvjd+90>9bA zlDm`QULyoRJcZtXr~j~W_mt}4Q{crR^S8J{{{EFL(tjg!(#&<{M2I(n+D%Yl^c4wQ zl&gviSb)DcMEW%4I$}TX-+T_D;_^?Y{OUFct2YPUJXE=PGZc(cX~F#L`vP)`QYwki zFE&^qe@Y+Zl6a98#k5;WR}biF4v1#vNZCw@+psjN$blXdkrtrjt3c_V%DodYQdvBgn>cKxDO-`yi8b;(l zh}|Sodwo287m8>*JI!Z0{ULgnvaiF_w_Br=P8nqBqhOWq#ons{Qsvpp)|pByd};4+ zrykOdf;>j4Xs%|8@c9$!v`j^7{GJT13Ng+KsjaciksaV7E$F9K>AffmB+!mT;$kAz z{TvWrtw^tU7ua);o-Oxuouc%Jr0REnZ5^!0jn9Ah_h(xEE4x!xae#u&OBIJGO6W8w zMq(I?VE%p^?8WXzIT zF*&PkHC5KG^G=QImuU59wtbPONp6SQefHokb2p{K2LNNV6&jijG=z0uS#@GVvFw|@ zX@`etk-FW7tJXPnG)gyR%`@PZtcCNEZ76EEASu@@iW=DYg_}P;ukYzWIaBvy#S5Up zC~K9VChceG67^nF@d}RsiRQTXy+&cOa|Sil2p`nDKF*&;A2lJ&Tu3B=mD81K+uIlA z{cb?)P{aeuFHMJ+mU-_$lW$UKw;pQt28DY9vdce=^($6);U_!YBEI-~=qG#tp{4GnA?kysk( z@?xfDKO!U9P>dQyQpSuHq$08i=W8Z!GrCJ*hp4hl>Q}Wn2qo^1(YTN22cR`kOUZ{K zXgxRP7sF$y(Wp4G9C9Zn^*yD+>v=r!vR;ZDyxc0%U06LfZnIxxJU54S&*;bM6SRaH ztUA02mz7qRz2Zxuea{nK^{EJ>tH0wH;7#V(`4YU%d2!k}%69n%%@S7>thwiPuLc)W z>V5}B1Kk|(I=n_P{ky#z{>3=(!nTL8<+ITPC$?V1RAOLi7y?F4f@7(i09(@#Fmn=|OXUK%T84m?li*q^LttqW0wO2D zSUM5#PRHf;+2E=55H^ELD@ZIVD0=t}D3>$yp-jq)P;W5BsM*?j23;;%L z0)PRh0Q~Plu1HX472^d3*I&HF1e0SF;<6+T8WklG(8**mCcbaIIJf&kjt~_l(WSHS zp!_2MW8)j9M*UtUj%h$BjRaU>$1H|k8uc5f6JcuDZwQA|aYi@(aA^nn(cEZ3@f7h1 zQ;adi4ATfL1z#}Dj)V0gtBQVf-D)=<6V4zyE6CQQPcWlj0!|1Rg@|CjEn+BZOnI2t z?NNb$5%P-0VCzEjf4qH#ee74g*FvY>n#rdzBQkH^8Y*I;~5%}khv0y z5Dqg5=Do=}tdjc>&T+3_Jz&SJhx553f2S2q<80a-F1X?u z<(x-)6Bjd@QjxO*J3jQ1@qw1shPlVo&2(@#QH6v?hTB zV=!O{#^Ax;S)b>cBxR`!ox%mY2UO2$I#V(ug3L)w9fqo2o7!*;EsUA_vUDy@eRp1* z7Ls8Koo*)^v|P^TJ&mK|mUqjW(_Px8-Q8i>-|e~wy2?VdQ)tO3Lb5qJ-R8qxRg4_d z@U!uDLk%O@o=)4Ylh9D=(kv8i7VZXQ1tYMGnn)r

    =~`%$ts)+~-9Voau<(6*lBT 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

    J|dY(XQu7hOM4SV(4 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 k8PR$Fh5(eNIl|a)v7nIz+a8KZ3aE6 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 @LcO+N?pb(9E$n{9YL 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�TxU^tA-f#`uN`IJ>*%2(JV%1GC-qJ6L_B< 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%0DSYDIpnJSu&2CMwL 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

    hm@0)_KSKr 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 diff --git a/airbyte-webapp/public/logo112.png b/airbyte-webapp/public/logo112.png deleted file mode 100644 index a0f50b6e46c7f8b01feb07df5767b10115a5e076..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14871 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 JPDHLkV1hn2&3^y@ diff --git a/airbyte-webapp/public/logo224.png b/airbyte-webapp/public/logo224.png deleted file mode 100644 index 941e0a7beacc65cc121c1fd4cb1794c5ea2c01db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48413 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 diff --git a/airbyte-webapp/public/manifest.json b/airbyte-webapp/public/manifest.json deleted file mode 100644 index fcd8add36ff12..0000000000000 --- a/airbyte-webapp/public/manifest.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "short_name": "Airbyte", - "name": "Airbyte", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo112.png", - "type": "image/png", - "sizes": "112x112" - }, - { - "src": "logo224.png", - "type": "image/png", - "sizes": "224x224" - }, - { - "src": "logo336.png", - "type": "image/png", - "sizes": "336x336" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#625EFF", - "background_color": "#F8F8FF" -} diff --git a/airbyte-webapp/public/newsletter.png b/airbyte-webapp/public/newsletter.png deleted file mode 100644 index f49f174b00f457d33233d69991efe037c47d845c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18353 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 - - \ No newline at end of file diff --git a/airbyte-webapp/public/process-arrow.svg b/airbyte-webapp/public/process-arrow.svg deleted file mode 100644 index 1258bc739c8a4..0000000000000 --- a/airbyte-webapp/public/process-arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/airbyte-webapp/public/rectangle.svg b/airbyte-webapp/public/rectangle.svg deleted file mode 100644 index 66aa72f35d110..0000000000000 --- a/airbyte-webapp/public/rectangle.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/airbyte-webapp/public/robots.txt b/airbyte-webapp/public/robots.txt deleted file mode 100644 index 01b0f9a10733b..0000000000000 --- a/airbyte-webapp/public/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * diff --git a/airbyte-webapp/public/rocket.png b/airbyte-webapp/public/rocket.png deleted file mode 100644 index c5cf200f9d460a520a0ee0a1948452047305e37d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46928 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 diff --git a/airbyte-webapp/public/videoCover.png b/airbyte-webapp/public/videoCover.png deleted file mode 100644 index 402cdfb7e16dac987f91c77037eed7bc0b2a1c5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 109073 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

    2=!tb2+xj9cJl;6C7gi{K<`ZT6pwkxobiKr> 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 Au>b%7 diff --git a/airbyte-webapp/public/images/airbyte/logo.svg b/airbyte-webapp/public/images/airbyte/logo.svg deleted file mode 100644 index a2f78bbe39727..0000000000000 --- a/airbyte-webapp/public/images/airbyte/logo.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/airbyte-webapp/public/images/connector-builder/import-yaml.svg b/airbyte-webapp/public/images/connector-builder/import-yaml.svg deleted file mode 100644 index 62b89447dcec1..0000000000000 --- a/airbyte-webapp/public/images/connector-builder/import-yaml.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airbyte-webapp/public/images/connector-builder/load-existing-connector.svg b/airbyte-webapp/public/images/connector-builder/load-existing-connector.svg deleted file mode 100644 index c322290d539f7..0000000000000 --- a/airbyte-webapp/public/images/connector-builder/load-existing-connector.svg +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airbyte-webapp/public/images/connector-builder/start-from-scratch.svg b/airbyte-webapp/public/images/connector-builder/start-from-scratch.svg deleted file mode 100644 index 7b152f391e4ef..0000000000000 --- a/airbyte-webapp/public/images/connector-builder/start-from-scratch.svg +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airbyte-webapp/public/images/octavia/biting-nails.png b/airbyte-webapp/public/images/octavia/biting-nails.png deleted file mode 100644 index cb2073c17b254a68b76b65b3d7a04375470dff1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19048 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 diff --git a/airbyte-webapp/public/images/octavia/pointing.svg b/airbyte-webapp/public/images/octavia/pointing.svg deleted file mode 100644 index b4453c1fb31dd..0000000000000 --- a/airbyte-webapp/public/images/octavia/pointing.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/airbyte-webapp/public/images/testimonials/cartdotcom-logo.svg b/airbyte-webapp/public/images/testimonials/cartdotcom-logo.svg deleted file mode 100644 index a9e5e18e799c2..0000000000000 --- a/airbyte-webapp/public/images/testimonials/cartdotcom-logo.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/airbyte-webapp/public/images/testimonials/cartdotcom-person-photo.png b/airbyte-webapp/public/images/testimonials/cartdotcom-person-photo.png deleted file mode 100644 index ac135a7e079b05913654f5ab1c92a25e7cd710d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 268490 zcmX_{cQo7Y8}}0-C_$^W2_43_YSgAy(`vOwTdlp-j2N|dl%jTNYZo1~_MQz&trDV0 zNbFb@vBj1rzvrCi`6DOieE#_)*L7d(eZB6tPYfPFF7RCd000o(hxeWV0KmQfeVD+s zCj;2oc-j}x=h=h1fQli3e*l0mK=+>Z^FZr$lu0_#G)-!i8T^JWBm#ie(oDlEB?jQTlnk2h`FIK3_5?Bw}u1D!&dJ9!pU=mzQ@bQCC+m*ttVqZbw59muCjaS=r4iE4I<$N zNNXvXu}YgO1$>zPny>y{o-C^`kQjQ*z%uSKrWC8wO0`ifFo}F<^y?l0ll?Otp}3gO1P6?Apn}9i!L>YUi>*l)HL$#5k~}-0MTq{trO# z(bS{pZD|Hf4&Ze;Z&pq*Vl`i`KxtBMK)&wGuZ4P-K<3kmSUrX#KbvvXsn~aY=k%>R zp~6AF2=#o0y)&_e48Y!hbDnf-d<7wxXPd4|4Ij_t0cVAs!$yq0O64X^>nFIyaJ783 z0=W4PFcU)Wd`a|QuR`-?&hBQHjYawoQQ29W;WO@*z@P4CC4;t0q()BzNl>C{dKFl! z8&Y2WX4weT;#4#G$p#U&Hp8wz;a1b{b_O4INY~ec6H|%$$C~tGIdz^X?FbwEt^?@N zk?9%`MLtY8xXY3>sL%H@?pKjXzC9r4xp=65n0}Fp3RPG3g_#% zGK~9_zi>iuYSRbM9D)F%CY(R)*ba>X&YnP9{Hc5UI2B98#!)&BBUh;+p%)VL2k?Nv zp(&!w8h zC|3s?gDLsAC7{kA@VmJKL?!__!}XQjN)r+4Wc{L`s2M4*MV$&;J)jg9R}?BS?8P2? z)kDsFz`l_6!2t_traK5|3z%y{W^K86nrg#e0Ox<1?)<1#%<$h~A#zM7#O(rBe;9t- zA0mU^rDB5Qd12FM*dCm5T(f3Mv3|VTSZuiA+_?fUc+%-B?ToM#;Eu9L*5c^v2G2KP zp0IfM1+b%2UF=XLD~8-aJ0Z=WmWJhQaD`yRqq$QahY>*OdXvAtMe5(WF&JQUV0QD7 z*08S6i?F&ZxEX&o!yk`!SDO=Ds0z~BNxk_X{G2>{`T|ivf+;>b$rj~*WCiVpGzNNn z&>hcRxv~HC=6})MR|q&EWkk5>dZAmg`N^?py^rqueG$>(HRYYleC}=cnr5s$0|OSO zx{VaViLesY8L-SiuMIS|{7tzl$)w?&qAVYIA5O&(@w?;q=BjLtKUcjEyl2p`OT4lf zk=?7MRF72P9fkqR4Sd4-G{%4bEQ^fu|Eav(kX?lh|GHScbtSC@dtTVfK0PZBt*1!d zFcV=5Gt~MuleOV^bu#2!?&_{v9m>bX@VGS(VpsVxrk-+8D?F`K4%hI?eD7W=2pHTm1Fv>(yJ#3gFoda` z8t%I``Nudt;zJj^ApGOd)x$apdb`C>eh!7I7yIAcjv|L&7;@qruBL%V= zdyG-|o4Z^yqIjKr6qraFh?bfX`;tfCH(F3h0;1NBMid1Q;ju!MA?Mj;D8+MF3Y@N^ zkPOGcNu|Jee-yU8A;JyU$ZKO}A*Fop;B?u^SgISMx50k#cb%VHZ~c)g$%lP5Tpwvo zc^%=V<(XdEb}Dl5ndRiv?4ztf$tRn-DGK4KJ2k{yzJ9Y5{QDXg^8 zI4zUlgHc?pQ6YrUa$|43!gxi*I?;x%z(oC~?#$gbpIT_0@pJ*e+APxd*#QX`pP83 zoLL7bj$&9&Ros<^Cv@$&$?vVc3tPpXYEZVNg)r#S=ieLyjgN+J>zmLFiY7kM!r_N+ zi>SPSi|>0c8os++j6N#Fn@%p9tiXDYV$&AzgZBx!^~4v$Kt)KcH&1Qrk%3$@HxO0M zjzY(jp)32h8%X7d@8A#_6c#$ zc!#-n-D8w7JS}?^CRbh`&7Ce%q(*^lnwrS9gs+=0!dL|kYtm|+6NPQ_NBIj3i+#Jw zVOJL8&`EWOGU2OwBjK|q;^1+U#|2peEb56IS^g}D1DIVqb0w2{Ni1n6zU|gO)t4Uz z0iMOfckj3i81@9dz)!ZuJRuTu9f>#sXs>LH;{5&@T1y8Pp>S@93S#cKx zBx=?*6$;>QooT7WdhV~{*f0YI9a5E{2K|`A2snnxqyC#4#hQS8$;U9W9rKfHos&bP zbp&I*IrA{mBldon4qxyG(bA(i5YL> zJZ=ZeQ$eBqvUTv3CPili3|E2c`BGnLRVk>%cPxUmW|-6ON#1uY{XpaKqdNg6ELRyRmY5-6kaw&p@0?W8vCzku_ zuH+{W6vUP|Rk9!W{mtEwLcF<59VL6vq;%gZljKiV z;DtDww*E6-3_QPe!RamIxkT+$J$l+@m3{mP&08&Mub6SJdeFzPO1=nh7zThEy!%us z91*4fZP8KvtN4qS%epBP`Z^Hrk)MxiFg4p$yiOrRqs<~R1-KfEJjVX?oW2bCJs_#~ z;@~-)#ET)hE)Vk^JC_tH0rzfi#R*1eO5Tj9^^yv`DRG~6SPK0|V$Ua#6&C~;@b>&# z(u73lg^$C?bIb>|b=7NLd~-LCF*z=)PV|m#_T;0|)`tE;je2$~PM$x@wl+SihxH1N zIB)8p7GI`339moiT?Cx5M;s^}Q1nhjMqN(KrPg5z;H3L`Pwx#`mleQ|BDW7bf*qw( ziX!2BWkq>-jiMTTvjiXc{lO8#$wPKD=aXW)&zk6$CQ1+SR!bR;BcX3!w`rbNGQXsc7GO4S$?@WP+A^d_bH^SUECy#=n%>a)MLK z=Pbz3I5h~BuAklbSqxfz!B3TDUUhV+;%t7;Y=dVxVqNt!JFdfpWdxNl7r=AcXDm+S zgj$FHi|k>l0(+Ir_NOes`NbCA}C|#3FZQ?gi3lN(t75BX`f)!9lz{pR)fUu~;6xsY1 zjX#ptDZ7kXl_3#qc~qlzYyR0nWJNtSl}J(0r=+Ofnr`68NLmsh*5>ybRupmr&f2t$ z*jL}yZr(nWl;1N?|IV=b>XZ5}L-y6|eru3#eN%j?^ID08Ci>gR;+wMDIT6gr3ZQk~ zo6pQVZo{$5mt5r9hUcdivK7qodvi0uJm$0b{p@~=keI7OFRaf-^fvH^bwo$=FOWwF zO3H0p>6TChPL#i9e6IquiL0TgJjLmiQs4^(X`2yD0$qPPPe6{46iE=+>YVWx(!h1~4~?D88)3!9{D0!8_Q!X#J1!oh1r_h z3_#MPlT<&~+ZhWgDbx9saF<@_ZLt$R1Pq%DKciLd-g=4xWLkF(NX49!Ndx%56n03# zfU+{8rz|hzdrU=rCFppAEu;R;5w3j18M68!i=fzTtUl& zWtF04w+S`Zd_f$;9?Ua)k&}e9RX?>J0#D<1CO;h-36{+bpJ~-re2*d77_)8~F1AW?-oF zxFU&R`3ErA+kmei!vCu>X!QeM;@$X=c%;YhQU={#$-a>hu4MnKf8}uH$fC#akwc_S z*1+78$4Ky0{+hBPwWaw3t^a(yB)h!Dp>>i;#K^DG(lDPeEoZbSYA8r-&<3KS!fRzM z1|f_ZV}k9Bs}ZLs?P}ryu?-_G-49Z4mLL8A{cO>%wftL|KZ6RcQJ8G|vs{AON?zH( z!5SBY3JLdbAYBg}uCJ@6yHBfkoYp}&NtM&RCHiX^Wgp!1J07&TarwU}tWE!nlXX+c zQ6qYM#$S-&HivivCZ8H2{^B|+(TDX7f0D25ds%I>B7DYXBFKTGvPue**!qK1#ky@c zU94g|tPYi<{sh#E&6$m?wwLAS={m79Z&-?@Bn`y-64B z4H^ZY$|72mL}>$A^tuK+!=C-D{;!{UOiwrO_cNQ@U%z#s!=q-%*HS@IZngxziK@Ca zI?w>TN1lo;+bqPnIH>xbu?r#}#&L&8eE0`su(&{(cWwvozNs$f_ zsnZ`5s?-S{rDq#8nNB$3C>XPT>2vD9WfK%<``qbO!5h3 z`Pkk<{^J$8Rnyp-=7y{Ye*M2?t=MxT%?fqRVWhQbVMETu8TTPC2AxKmBaG2{qZ|af zU;?D!RzV}8oxJ-ZG_w9YUZZc}$lPt}wifo-9Yjm%Zv0qSGJ%LwT#v1*RIf$g@A!r~ zc1JdBUR#efLyeqa&I#63jwcm#E23fWl{@=HeC;0V>Mfv^oEaA>iGXK5mrCndQyh4u zzu`>_S+;70}@CFd|sK8AwMih<(V-#3o z8@{_~6>kXm&W>U(XatrmuwZFA%CXBDEL^g-wLt^Fds1D8E;$ms(6qMe>RNzr#xEbM z2t}+Rt(T55$OgTe5%Dz7%i-^^tJB6ST1E6{*s5{O5q`EWME8HEgAUc_Ab0qy%F!`$ zy?g}RyAK~zAQ<5eZE2W)UjATGr$Qah-kg!G+ul#Bc^bd3Zcm&=NFlAiWx+|i6MQZH zo9qmOin}-Y6a3E#i6`T(tKq-yTTi{WKiH)d!gJhdr4>%f0Q({|x-*s?0KvSeIpKB6 zFA=bjWVl^|pT?dl`RAirH@X%|u#411MAzSq6}bXjY`LJ@E82VqdSBvPs0YFU$g=Xj zwCQQN*s4-}HdaW}H`I^~Lp_aM_Fna4U!l!VK1R^LG5$$E#H{_SbH;u+;@?v`HC}ok z6!&WMo>2Dva~ml;?**mPV&d%rL>2-c-#$bT9+i?th^pw9v%X=a%UH^B!-@m!mxAfa z)i`2i4z#Q1;{A*4wWI&Gjt<$7b{4_$2O7JfD$@EYNm3QN0=kNkP)$R$<;5}}0#DjHO!vi`=Nchgop&$9}hu8CO+FANF$@0#iHx&C9 zf{j2FQ-^8uRmOs*AUG`m5=Hr~r>F3iv&)wJUaSQfZC(KT*;%@#W--$Y<>dbAOQgAA z(ActP@#ypg7FIUz&N;Rxj6B6=KUth>EVX*ZU*iSZR+f;TIBwfiZ_PWszajC)?k7V8 z*X^l1uQV0j8>AbB*SGzXvzVk_*;rj@(O>~*vh;M%em+YcR7s%UD*e=5qhI!@AZ%66 zG9a(vty^!stY9!Ihz-vqLTPrSd!sITE1gjI!=ZlP6%?osC=VQ3p`|vgWV}$%(4WwOyX_Yute$N|LN-~jSRuY_r0R-{IA9;FRs$RSv zDMW^^p4P1x(!{Y7w>sM|@Ax|ug?U&XSdi=Wj8f84BQxs5aNjCO+n%AO@PpPj6Or^(zP?ENvYUSF+G3VJeJE1--Hdm zkiBb-DcM(m#Rln~wHfm2Cavvw@A7D7I!N0T$GKUQh4gO?u-jy@6HVkRqUTF-52OIh$$*C@DIt~w7^9Jo6YcId$ zM>2ePF7JOzuU-7yR)X;J5BAIf@R`CkCWzBpHYY$GP7&HYLg`_MNmF@<@hFBpuf3=c zPS@@qQFnBO;Mt1BpCN9yH-s5a+swe^(_6v!{?}(Bc=!t7bV(E~ZY5F)HRttnLE#4A zXHjB@N;dm+YD~!|&RgCI;8pf4qtSZF)&RtbLy|J5mgAh{ViA-zg!R>O?_n1Nc@P3? z8*eYqpj-GSf2~$_ETyq+{s8lELc+OwI{^AEqvd8t2?Xa}r4o9*5lxcsgtEpRq$WBpXigy7L@>o1m5(8Qx3Sqo$sOZmPS1 zR{bv3flu{?ref;~ZLaYn#)Go^bv@hr2k}=lUH`i`_fygPFFQ~M9c%rup;sv4#Wtsp zp*-`?TOC|06U)bnE7{@hT1w^$QTA-%^G?5t>0In)6tBzYM!~=A2cLv4M2Mn-?2VNo zV(lL0pkwqmS#zK2k@mAAdLDdHPZI=;r*3r07ar}uj}+_#yi8)_T>H(QGThzW?cZf-)M*ct;&gs`uEo^+BZ`^rW|_fi zCI=NZ?(9m223yjKv_?flpN{A8E%@xY0fEZK@Emc@Hz$a1$DTXDR}l;!8xD?tAuDt- zP|%?eEjvU0jE*CA@E}AZH5Jm{l=b4wGv#ScI!Z<3`nH~xO?Q0>$oCMFV5i<)ozeY^ zK%@l>d$Snd;THs=t3Hef{<=+YSu9Qm0#nh$ZuOtL?L`2PTdGr4Rm>Rq0`_tq;kQ(i zgd6!RUIP2azP`Tq&I)?7Rq^ISo8L!S?kUGzZG(a_*Dh<|ukWazk_9tVrA&9=b;43gtohYtxdU4>m%nkPcEggZ$l1O0d!qd34uBSQ z=Ucc|a3J0rw7Ps}mu_p>^0WG70?3uNd{V!nh5PiS#2M#8oRCQ}PV#~LBcB~a*lB?a z2t@(8EOSX;#<>KNbl8NI!u_TF?qAyghpI)PD1z7%H-Fc#p;(cZW-h-_a12-xmn1ln1 z5RDDjRq9r+rpt|pMt%b$bj1a)KZ@wzzZ;A7s>7mO;tW zXG?y$R%f1d4q`Ju`0~p~E-Pt3IFcf2ce-!B514j9JIF~`nhFq6j3pfD9?5W|nV%)R z{a=iIqbD`5=qAv{ISxK;&3a%#4R z;C=3wD)3b{XXsdv4|L>nhIrg_CafHD z7>i|oD9#~5y(1*=-sMFBy2Qt2tU*oY8Y{p30tI?rBfYCX6wYS&{bTcwZkvKcHdI+> zJ`e*xwmD|C8|mQu7tpu;rUm+&ymp^EpBvHTejNHD?_h$gw8Rt2T3C=|JLWrs4{GRd zS+_(`N9n=k5#?csv+mFJ?Fo2lYsHq;`tUjRb;OGmK1Ol2CcIBpa_`Rdo9MT8L4l^(F@&m8gNh?3 z=836lm%&juP$Tni#^XoVM#6c^K1X-H2s9LKSQ-20_g!<*b277YiXH9E9brL_%`qLu<8P!BV(YsiU1i9+K39xlj)I( zSD73vm|Yc1(T@0nYm}!+_E_h*;@Y3+8Q-!uGQUbmy ze{b*lHs2gp3G$tJKYAkS${$!~Nz8tu<*?0N`b+RLZD%!AvzzU*>bT;1+_cz9Ow1_D>#FPag{tbRcCCKgdM?&9&2rD&%$wo`N* zFyJn@RR)i7Z}_||Tu?b1dS4Ltg+Sov+XHz(5MEHsqbOu#N}>y2_C2XL^lvC-GZ z2R7iS=Ybo$gv=LO-<8@w0Ybp)7lN(K%Ttwg9)_~Xd(9T>8?=D{u_M{1gLc~20CTER zh=sW2fg8iE{BbdMC({rf77XXGn(lQYYo5*$ZQtNm_lk>)eOsfo{yG-Y?baNDcyPCt zp*I$znGe+0*uHNDh(jE>J}zjZbPCj=_-z>Qpqk)$Vbu{?iY_NBIQon)R|--u(RM?E zL53<%VAOSh6(Kc&-EsT07wqdkf=@YlSVO`zMS2!8k47+|I z>)j0&(^$YRN{Ja`+uiTk&z&k~zin$}l60@G`zH>+w3nM>@yZ`o@_iNhXGO~btO7ZA zcNuVQ_uKe?EC2@=#%8Va&L@l$=ZKpG`G&h+M~lNsI=V#5WK&W z0>^gM#-e(XGj}B&b_9Cbld%>)!h>WUC^Y4+(5`#6Jqt*0-4wQ=sq4~gUJV%4KADzc zQ2=9P4-oe{{$(-Ac*LgZKb&`hg)cAZogg=`_8-0JZLRkFezY|}FOW)gd;4?hs}(uQ)BZ2E z&H(a+K&K~IkO9o0XlXXYST`_F66>H?RYMVfwJnx5Bg{l!Z2n|O{FN%2 z&I}*ajU&=M6PztRvcHeA&evv#CNe|2;`4`%Sv@50lo^Lk$qd?kqS<9~k7935$cGI2&+>BJ@1r-s`VDV@JU zsva@{6v_lU1m;+^L3c4^vfwUPC=Ec$vy>o$+(TWbM*hh~+Hk;MFovcQ!#u8feP_=tO})%^z1tN~ z;ySS$=}EVWN4Z?HyqwQ`SXL;a#u`ee5qDs1z<^QV5^&$Xlc72by(}h@k|r-A*3+G4 z3Z_>=N>W+reEZTJ@Gz^<928g1N8?`kYp_O{LBrA>W{GjPZ{!Jl7ebjzYhk`mXYKdk7f4X(hYwT&gYLESmJAOn7Y{fcDhM=(6g758{}LSbwxP9!d6J8RE|?~SkJk0 zU(a4Jbn^{dRYj$6WF-2T%W{)uRUEzGvdEKwsXc54P5z9>Hqka}v=+(%7<{FQ7UsMW zlg+Wo)W?85)hARs;I!1a7j^rUz*}cT&AjG)Eu~}c@k9Ni!T)UUjK!Wy0H>KG{R(EE z!#sVc2G`veEQs$*Pr5&~~+aG9_M0tO5oOg-Kj@4BAsm{VQZ=l}wDzNPVW84{ z?lb_iV+UC)oMsDM`mJ#wn_}?{m0hKBqJGaHC=uR#`Ef@AxAec$)7-z;3rk7xmY;1) zn@JeZt(m$m(%%7PN_f2~N9IOvZ|~m1UScpxg!9qnactHUJA*uAtBz<+rSS&1M%jpr z`f>l$?%n!rI5~rCLs7_&qCqM3gRi~C3wrhSHYm$x#p*i=-^W_9dKKS)TON#rc4&}8 z*O&OF!gJlW1#Xq;fzocL2k?)!VB092Zsyeu=lFeds-LY@K$&YhKFBHjyLgO`cjLvb zq|NQof0Qgcbepq5M0W9WG)%K~mp5u++V_vGt6sY(Cx2)+;E7D@2pE6QN#S?&m!C%? z5C1m5PQ-3U2POO1`ZFqvxU+6A>ToI$9q(H5+{V0h!rSGmML7r!BpsD~xpFImUo?yP z-{ACd>B%o7>7CqMx$#w=MGd#ZACu4K;(4dX>^GMIgLiKOyyct~)lW$}wpt8Ii6AY3 zcfD<)p#{}G?#l8cYr{;6Y!8?2L*BL8mCoqseCDU@yT7SXzfy-$&27Zltt3O8Gt^l9 z@_8l)>cGS#bZU!^HMV1_m`IF1j=I>a@oM^H4ALXdCuEcsRA-KGnU~DE)^WgKws|K% zwDNHl@!6n=*TRlWg`7k6_USP zO!ATBLiR0@-HJ6MkS|jx_$Tkzo$0rvFdvobT{us13eoe^!Tb%Xl}&$f;&G~4}e*sql8@}Zw5hq zV9HhTFZk;9s<+eWsWKzBAdklYbHLuRM}tX9Zuy1e>ps5>1*9ft+0Y+(x4drJ3goIw zeVO;p|HUI5tD(gI_D8RZ45@cfHlPEb^3a>ZiB+s%(_t`ee+W=%rUr{qQ&nAduoE|C zWV#y1k!es|XN^|zICptfcZ=R(LoB>K^enrLI?veB2CjPSX4cOO-KKgA?A&QRYdicG zg*-k3ss!axSY3TlQrt=NnBRkrPcoWLqfY^LY;<@Fnc7RhE2QzpFr{p|?1pN>8Ggl$ zOIbhaEEDMwJy}xSV5PPzpwL|5c1F|SQ~!}3|D~~a_SSKtuM;QZ$c*bh;H%vkh5zp4 z{Jcj|LEy)=S}LX&nx4521sTh_n5a?VZMrMX{bo^vkuEAW4~-kg;|;2gRtk+{%HB}X z0bs3nTvu%A5Lbp1MLso$f7+2Zq`b~Vq%T}?NcsXP#{yniZvOQWPV^(PGfE8p_PTbB z|2V41Q+~>Ty={{%Ds6JEQ^pQ0B)RD)&L!?pqqrOEp9~$lwz7S%k2NDLV;H?>c$r0b z+2PM^k&<5}zvg&#!FMdx_}+f|<^D-I`JQUbUhiu|YlrDArkF267FxCpS`?M%_Bn}$ zO$dLr>s5Ci&hrgUzqeAj-okFeEzg(KsO!plw7IeIv1s(lec3WTaiP&~1uN;Ze%}d< z-ZBLRq;yWbK*65{55%b#a3EsvP+LGt|va|0C>^w%@l)?kEi@gOlw<9QGb6Rp;1;}46b`UiqamwZO`x4^P+ztb9tAy9LEn_ zV59nJB-j(j`YN}`+n0q-f|5RK!%16r@RB$q_!6FI>8s_}W%W~;Xd!pz{uf=U> z=UOJ_Ba5~GAz3*vIml3)37osmQ1oh0aAgMVM7Xmj3J!z&ZyrcM-hKA(v-KR@d*}wb z3&q|+UsYAj#vC27tQ{P$CZUUVahF@{&3k(}7L#?ZeUcu^8Y+?(VEwl= zkP*sud^A6e_yp6qK?$s4l)8e0X$pI$n!M$|Fbr4@F!f7a%c#XVUgfy@e8ltx;FJdn zQXTgRty^h?(D+Bcw&8;`xy_W-YK1*jnQ^R6PUS^g=-*_s07O__1C+4naa_suaE;;5 zv-A)nVQE4Y?NPXRLB`Q4`N-{SEzM(u8KUUilraF)(ToWBS-5mG{tkR)*`LW2P~ug) zkQDB}Z{0cck%ZXhh_=oe4!vSjDQ4#ccqy8;^w!4KT!>y>G%ZLlU*UyIT;3hB#JNU@ z_n&?PRCXmeZ10ofmg+s z0ar8QlTx73GM5eKH5~9xZMlB*WZ=`0sz^bg9!L@$D|Gcw*JtLs{XzoKlc@Ne zu4W-v-l~201+3CSQy}5;gZs=F*~|@n#pz*Pm^5wC7|tiL@dI=`zKIbuhc9qAx zfRE^AczVPrCch2G2u!;`riPSXhK_;rxEyHkzS zVl807$%-=WiM6kv{OZ$Sxfg78A*S=@9Dd`wZLDIl!EW^uv9F__!y0^#e)fm-`Dc_L ze%Fe@U0?gGT7RQ^rw_4GindWZhtv6%A-vT;0jGl(UZ(%3#1m2fZ9DLHw%7#?o(>i5w%t4L2Lo?gd6%p$&DJm*EN*fL+euV#V_8?t>)uNgUX~afJ`!%dKf)24|5ItWC~i3ra$I+ zn(iq>Ns%h-;4lq#y->jN$-yS?p!PBBkFm=H=3`QU?cm=Y1t1)RWu9Db8Z5PIU&-O@ zN%Gm!hVsmk(a(1}VBh;5x7R4zuQgcM1vHMT35i{p1q{mie;v7>CV2S^(ClJmv!IAA zy;7Zug;Yb|c39{H#au!VJ#cB&6rRKj@%|d%#VLy55!$tvAUX0_L zHhKtZ-5N^2y0+}P=$@c_pprE;pw*jMRs#6Pi^+NSTH{KAkGg7wd&B(Uc6aEbdHZhf zB_7Vu_1q-c7i?WSk;pFQd$G$}s{tf}%DGD&+J9yR6_^R#Ndq_uj8yTY4 z#T!NUtcgy57rDDr(l|;$;EhKH8IZDyd#!QNmwSJ_gl&_Ht0j2SFDAC>M0I=qj?KA# z3xgN5DPzCHBK1;@aCL+^^zQd;Sx3)_JA%3bt+Rz+MjcvOT3&7~&`VX_PJIv%5U@uy z)Et>?W)g53ER$BL*wnqiY3~Z+PC12M{}*+f%}rTP7l86-erH5@YGNC|6p8JV+tg z?V*JBpELuDBl>gd$UKaXH zTyG=r_zcjU{K&Iv+x^KAKkFxPAMJ&66ai(|=>8XVH0ac5fkpMpdY(>aI|-#%Om1%OOT|LH@_YtO)b6{TcvJD6omABaw|{Lfzh{xlgvs<-af?4nr?Ga7 z$lc0fIj|9NN2Vw^@ttl^K)@;g_Bv+G?$-QgIoC%S8Qhmu@4Ct1!z!hvfT!)5(%)hB zGrg8F%cZ4iioc*x==R|zmPJK_Z)AI0A}K|5@gTakgG(sf*OKnYUrgLlukH8D2dDid ziyXRVc^}Qh^jtK2^*JQcmgDDMuYCEDf?~}j47R(My#qn120tc@gn@wNGJNdCKPwwpaH6`0;@n8tnIPE^_X0mzQELy|!Yz&G*RuBLl-Vy-`- z4-L@Ss#sxuXuGj|S>c|mc=Rn8<@TFr4NDqf7nNDF%U^KXG-x zV==~)=br`V1sy?y8aB?`8qb7v>@mRgtuqS8t2fu>${d|eHJ2m3lf*!8Ia7YGBqkz6 zMFraRb6Z8yWakGTjjkO;mFx1o9{Tr>H%e`a9y7JAbh^A6QGdBzm7c)?G7+7|Q%u}o zdLybXwVa;n1(+yF_2HekKlixo?C|h?B;R^K;>DGkC3~Pz&~K;UbcW6SQWN<+^y+kL zY4+xotB-3u3EOCr6KTtNdoK01TwtUR+PV!2+ zg1nzgO3qPI70M)thsX4fv77Oz&v}&*IWZp>H&B{PRXiDh{3%@}B zqdA}M`UYl!0>)oglP^+kbU5B!*gEh{c6%wV@aM7j3C>c zs`@4O`zy|zVBUs1O&f}$glOVh2JJdu#ia)e3BAfhy}!TXH%-@)YN49LZ4Gh1-GtW< ztQPnISC?7Ixt#UF&pi+egP=ArKD1I=%R@_WWu9^2Vz{(Y>8&5h`UlC;^RhlOe*eg^ z2fqIPZ49rji37@hB`Xz$UH>TC$$+JsJD;76Ff>szvSv>-89eSQ6B`Ulyx6>5&2`B_ z+T+T#TU5XFB2DC8f#X}JeSi7cPXZedYIU*ZbUUGvV9B}aZJ=XJ0E0oV@5iumF{qaym z&qt6_%5==!;#YUw3A$$HSWq>3-{r%@dq|G+>qY$dJ8cf>5g)xC@@k0oCo??>OBT?& zqZTcSlz!IB7lS%HvpU{Tn)Nm~EG@k`qp+7G8g24zHOeyYyWCi%m^LO&mRb9$bz806<0a~dPldcu);T4&5-who$8B9OIcc4warE$ez!&Hy;%d< z+Rn7xTx)yQ-n~~x*ZU)Lg0^k{9H^@NOH_C{k_cSQtLQ~)%pcEO70ygSX1jDX8oiZx zK;1g<=uB)8bXiE7EFZmsz8Ds-YbpN{cH3gmlUe?vBFyKHNg7o@RK52Fi!jmQxaa85 z>_HVEE~X7`GqDVijGotB-~}3|3-l!Z7){r61vH_Z(0rs|NV;Ff*{Ye8r7a}YUjKG8 zIjze5syC>rQl7mP^v^2?j2*Zo#1kTv+Dgtq|B6^%kq|7TzXwiPvKaTBa#Tz>K_7fUUs6mlz- zEXci%o&3sdRVYQ-zY!KlP5w2vw;1=)NA_FxPLZugj;TXkJ=?qB7g~%^P@)bYreV+= zPIouscg%^P%g;XSGN$i}Pdzh2F1wtW`<_4(axNH-*U=PZyTf`zNp-N}VX>RuzlB}& z>iWw*-oH<}S?QIcZL|vj;WZL!-pVf%en~@Pw|NubTF-{>4#d#0(n!4+#eRV1UDG@! z*{wHS<{fyqAtgZEHR(Ic>b!;x`1R?%5KzGgZA^e3I=>E)QcJl&UF>`6tkOEa4sD$*w3ZQ3v;|* zBvmRu(1&@l^mY5WgoJsA;`j6Mu@yj7x+FCzS(h1Wo6+F6dT_ZvX>p=NSu}S-`4Jal zU)8E#{Nu@w;!*|AWu1xJ$hPs+cM*3YkCcYb*dVB=-!}mwu?BS8H~5nXi+m3d-}gSXynTduD9e(PX~@(^zGN{n?t{d#3{>qvEoVHVOy z_EWhI>0Opn!IB^i<~v~5fOj>DxWA2)8#@cPpYl~#3QTTpX}7Bn+IT_)^hw6D5B}?GU`*n>2m$!G`#+30AvezMOwF`M^xkFKVJHx0)zEAU>)n0h$K_XjWYcm64x_&l$I=(@G;)&1h3}kp zIhDrPu$&v6U=-ezlGRVjfYTJ{`z#+v*)=&?+9goJ{!4TMLh)fZ4+~N4GA02BXHNw8 zWwW;jh7q>mS$p!&ENR7ra(jv&3eOWkg`Ird@ThPd+Z29ps#o;ga#@R?%eZOt5m-L+ z(R}fnVSirHG8zbT^FvFtcuWRdFyY=Ue6!4aEAVede9?N@b|rAOY%4k(BgJ?KUu7d^m97CNTCY z<;j|2;lRLS4R#fR_Ma|Qq%vdD$>CviThMOI&8m6p$}g#;<}YWJ?Z@%x4H-1?s3SPy zY+PyY>|nMwHR_1(fX*3s@4uO;-jt`GZCNCZ>DCr>wn83i$QSh=z6WuSEDyFMWw9X7u4C5)<2s<%C5EE@1NyqwNr)N9%s9a~cWRG>`p<3fU6 z?1vALv0(9#xjZEgn=jQE^kHdFdG%ldZnl;~nDe9Kuj<~eoYZ<@Kc8~0?-VqwdzW_g z16NvUsK*&B{yDA22{l=k*@xX#v;4-&f4;E7ay$@m_QpClfAp1H@%Yt6I>8K+fHAV~ zzrDSnp*MHa(FpycqT-Gr8Kvq{ zZaaAeym{D@t=t5n7q;;{Tjq&KGx15t;!Oz=tDm&1U?ZlIvcB$7kos$(10qZm`4 zW^X>}`Py!I-$ENqcgd2ThrQ2>M4WGmpU{UuzXzQEuArZE3j9>3-?(R}n!@Gn_M)(`Zy z%jSM(DbG=y^QQO7<_wBhuT{;%WW(`H>rd?wv(DCQ+ep3es;|-BgN4aoMxwzF98}dl zyjGi~9)eKklt#i>!zbytVX1N0pGu$Zn!`c#j&~z_Ug6|zAyx8`chxFBINvJzh=5l# z9N-#oiWfWUsuap0w@lg;srL2t3j$VOAJxegNU~XhUYs1#K(biC4o#cepQOi-u#X+G zGJrI8=GA|9u4qYHl)`}OJKdhl`S6cD0yS^KD=MX~3#|M9;g^c{{cU#d{{Y)SB)`*J zq!D#!I2bYe`0D18L&5+!(9ZCYSZS0h9dOyq^=i$4zhUz;z)qO$fWuy2z#e@Dz9d1( zBGGWsp65ZE7cCo_B!JAAg~f!6#3X%+!i;9ObJn_#j>gQihif1h4<&{krCrITpo@Yi zoUn`&<&1nG@Nw*TZfW2mGe%U)V1>w8`v^(P6W_r4z#4ffzG%+Y7RD6jaq(TBwyZB|SA`uv>N?e_YXT!3^Rq_qJZkHq9XM`pk2oCO{(@#?@#A97+KuDmuF zvTNk-Zpu~?e8+<1aIkfc7@mZA&N&}H((gtw7v~AOJ?ako^y=kToK+8Fy_`u7e9nu{ z&y|oLVOhlAE_@(0pJzbdS18(o@-v_p6tW_qYXDc&Xde^Mn`qY`8_?{OZ#7Je$C$mLSwYi#dpTtd5|&a1H4^`)VVkeeZVu>NUbG{mF|@^i zp1Vj5102anjM*Ib4#h(j%Y-@((PS*y#}FeAQr+>M$d(`iUSsQWd zXSt@zNpJE(GaTcbGs3$bV#!70!kw!(m>U9+{OKzeR+jeXAJYv?tAUIn0a8tBIWbj>1Aw}>AT(97np0a9^n z#Wu9CwK9|aQv>ui7Kq|{XzRC%q?#7M7gf?0vpKC73%a=cK=CG|;{ghKMD){#DfN7$ z>>QBmbf^~$=r2FMW5V2EfEZziYm5VIL7YNT7!c-0lVd9^Dc_uPVj2J=UWu>OY~l!c zW6cU0ey>kgvzx8CeVc*o=$N(jtE+2roRkIuNOL^~L8$&Pt7A{kQn0w8f%e$k4lBg* zXh?m;Njs7sebSZiI{6{48VB~Ymuuy|FY(%(=9YIDVU+`T)=@%fA}LB4)KiJCXTVRy zy|Bs!0CP@?WGMK_tpTUVrgn2f^W~gtg!l7IX{*(SP3zaQIdyyDZ}uE9#bd2OMnkRi z^Ye3I_rs-;ND-CAYC$20Wyl-gNfDIG>kIa+zkdCif{uWt2u@iZ1t1A%KxP9_nrv~) z#SMM+?eFM6zW+eCh`a9%XcYML)$xFCE`O#p1v`Jl_10a_W5OJWePH>c4aCXgexfhT z0h#b1bo~7D&uke$4p$sEMP+c0*>|3kD$W1wvdP;-9RB#^nA81^PfobcRT%TQIp#eR z&O@8eLpAkhKz|1GJ*CiS=vAAx(G1Eo$)W^Pr%^Wr?WX6M@o0%(G%ep8uj*IxF;%S# zD?~7n!USo>Fq`k|UiPO1=$gQyncTJYi&5VyH&cT2wwO*iC;NOp<#k)!uIS`s#2^Wx z)^dpgCd8&|_^UVJng)Y_!N4%Kk*6I*xSJ{b&thKZ5}GKRnV0_L_3M|Ud*kElNwvxYmHPATZ4ScwqGF6VPLz2Dx=Bo94X z7XtEgV%~JVq+!2L$Kwfs69535q8#gLNl}t;ro5A*BN_}Oee4ha{gz(5n9$$<;Scmr z|L;F>;vY7VXBqd8Xao4TVcKVZ`^|gu`eV9Y#N_lw48-f@lK$}K6$O4um)G)~98Jay zu=uQ&%dHuGu|XC;fbE1eb67=w|NFn9>+5SK+(oHm)H9)ucEvY-5AzCmusT5C!3O~Z z(D<=NU;Xa4ERf(Q<0L}^?gOCCntkEjuY2#yG)zrfKNQe4fm`#zYvX(Nq1V@&Kir4D z@6vJp@z4KoFKBKLP;yh>F9GOf55M+8917@0JFA+X21sQ9ZI4+qxoh+L)IRh&fd$77 z1$1O&gQ*rEKE1i(#4*?;ma~~?%J3P(T zw&ZW`1XBMRWH*FY!Q_hm;zZ6rpGX|D2{Rkz)zXqkHe;`cVk8R&HxuS{dpBnxVLa*) zNZjy0pB|mE85U!Lbz!ra(_k3TX>UZ6$(VY6m%2z))9*3!9n5|7k9yle4uhr+P1msD zJuU!}r9#l-jnkEMsVMP@@yKS2obHkfUbJ&mXv#@(sY97(;?$AaHKYxj>EkVN4jM8- zz>p+gE>vLW^)N_Z$U_2hu>ld$hY@2AsB)lYZ=|BGCzv#`I*Zlpv zckk)->sJiM#zYSvIh)^my=}@|qoE&-COl5`5yr?P0D;P3!3J#%jwf_-b}qb+>uX+L z_}9@Ehf8t^*5;qKn))-K@7DI$X>wNpy$CSBq=w#BlVxdHNzJMOW)aYf=WBqj2_auH zpkwZu4_#Zo`Aq6vcU_+r%PH3%M=Dno)!0Ntqkfl@tib1sjTK-Hp3!W%;c}(jKvJRt zRAJu6n9v^Ax}HpExrz9HCS)xZ?2E+~dvZKt&6MH|9|r&djM!X{6tQ{k@4LlJ#s~j; z(3J{YAq0!AR4HSIyid#3nl)L4M!!u4rDj?08x+R`7@K8*fB&I0LiE{vd_=WR)?+LpH zVEsT@(izY1==_xW!H{Ot8CwS6+{fRSS62iJ!FU3bct$tZH{>1#9JdWlz)^q5W^J|* zkhm>w7P)m`F(;VuU%h%k{h-5bou8d?J##5!g9Jh#szoe7C27Qdb+}hvzdUEc3h1p z2C2!RUdN~7qa#|cLe8Cy5F+3oeC;4i;iuOhP?|~77}j#R0Ezh1p|vwmcpU~?08>A3 z>Fo53`h&j2buX4Q97*gmNL^?HS|&{2rh?jRF{jB`in4HZHqMkLA#Ahxn!Y+aVSxf> zcbJ`feVF8lj>dgDJ3FN#*QZII%`6R3DNf?d0p>9EJ9(HIo7i*mT84ruxy#0NU~3mJ z$L1a;d79PyElyDvE;q3wNee6{oL@X|3?_X;nqwb(oC&~3qS1Fo0|qz)Xv@`xfeEGp zxF|NOgw|ln=ftnu>5Sh0{4<|_JUOLBSJn=oK17PtJaG;BcRN1aE~PNai<4ve&%gYI zg`nSj^ELhJzx^8nI(+hCnl`!Q5wkA$4ov?3@Px8xMLjp67sp5R)7$ry_(M8>^LzTg z|DS(iU;XcX^NOO?l5TEibb2iA4SYblySloeKmEg>=>Phk|C67KZ@&44e*E#rZSH{M zvopH6x#s7A>)YqTlnHYT7b_Yg1uk+HtT&W#Ryq-$hT{rZu(3A3dX~Ep`157DXL2uY+?tQYENIn+Z+tLS$2(l6(vo8LQYpHW zSSnr__?bA*YJuRsglwN%RvvXv;!*tHUI`0w&t*|k)I|evyMI%U*j!_l1OFG}(9Lyi zO#Ye$MoU~%w^lf2;wUjDFu{3jY!Vjo7R>CDp=`yWPuToXk;`aH$Owmz?I*_n#>Z@m zZ2)iqKsXP?EXmmpmjFV`A{zF^q8r0N^uzaW>Fo3ky?=MXg3OB-FX-L7 zpQsP6!x3@}1cYjCAT1)i?Zf+@>CM+)(-iUYeV<(l5d65Z-ZG?4f51g|9M7lU3=^6s z4vk*^hK8>&wk36ZqHuaeuV0+eG?eOq{0!$j2oV-se!g-(=I-7U(uP6+JO@YqM#ly{dU>>!(>;)Z#eSd&}?cy>)77a(`?< zhYxW-AF>U=l3uY4sLXet8ql@WubN4|PI_lRM7nP4rs4rLZI%IgTMI#1|8^T63()NZ z8!(?55*G@t006*lXJB70$;~7^Dl?N2%VqMd=YC_1&j7jsI1@{bb|o8Jt{S-=`tG;i zab@mzZ{Jb0S#xU80piowYg$L5nV+42xxQhbLPa+uYT=ESb9(QdNsPxZ&Ov^IDIIBM zhn)_`l^=~pG)6x1VL;uWOI?x#IRJA2zsV_pRH=BhVVvFyYkAc&_{l}jb|^+ndQOlt z!k0N;G;^B*BXee-dtT2yj(4d^;kq~# zpS;u^-_Se{@k3G?2u`Nh2>=}N?a->x-un-i90mvy8mumGTfhS2IC(Dh%%hNn3YP{T z5$0)WH!~rS1@K;PfN z9t+UR!Sp`ixwxNxae!VX71@CCYXfvmqANZS38H1TfyB_>J|3W#nfr?4vo{QF>}AKH zp&Kw~AW1~?HGq+XYnt6n8O*t=*cu^2#2RgqCTx1QrFgWl3-c1~)R;#(xk{epjkWU> z}+agU%Vue;p$zB6{nPy&6hYy48RiS zBdl%MbE)rkXxt0vcsSrVX=rm`xTD`FTuR(KOzXK|X22Zt3Mpn_XGS|h*YY@ddo7K& zZr&yHzYych>R7hjJXDJXLQ91~HMuR|^ZKOZxCnid`3a~?npWdyzlm1tPC(zr7r)7~ z<-upYf=Qo5KmdmTE{ zf8n)Y^fD)SC-g5sim;dm?5427q4j1!-4y_k4*J+>4P(OXe_0N$``sQ{)Z{D0x z6wm25-~NseMK-;g@p)Lk)6-)f<8*e%x!@r{Twh%98cc>`j=2Y@L*VQ9F7q{lUWb|P z7uPp*adSr}r)T_ZpPwGnd@*C5MSpTigQF8#XAZ3sRLw)^qGZT}Wn?Fm$(k0cO_l+A z8JL*wo&o(ZK-V}38X#*5nRfkWr=b@g(Bh{5B>{SIZrcCa!+_&OKyQ=!75!^rbN2ly z17zF8Z;#iUt6jf0$4vaT4Cb2^gRcQ|e3v1MTLuDJm(#yWZ1sLTuhGbDP{ZG%nS(hl z>~@|zg0Z0)Bdw~39PK_$XESnAF}pI6EE9j|bT+4W4dynoiVY}BQr^&4YXDjvg5+jw zer3hWlY$>ZH{rN)B#b#84d`TiL<2C{5g_k6Oy)9U#l7PVJy)usFB=Wr2q|WMX5DZO zgMlegn!6i}Fy=blZ9N2AGv9(mCc???K8dvf@!OcU=ZUEtnz{TI20d&4aY8qtq@IQ5 z9L5oA*QiitH1?H`^N}{UM>kWL+Lsgr16qd>&F4#s!#R`2Kz{rA=L-%WL!I#-e|pO< z64!~u_sr#6H$)D~;flKemC}YCaPlOzE36#wTYvxKkJK9v$zz~I>Dq+B`oranPL4)Q ziu?J)4ILl#sNW+xJAIjF6YO$&SupJ(WUz_;=8~Te{5=TzT()&Q7>RI4L{S=Zv;jz& z<6(~m{V`qMT+{8{f<{LZx}Asgx8J>?*?gh={b1L$ZM zLXzCWeUoVwpxZ*N{Z1X4_(a=-4mG)J?VI@)=Ut`Hm-wQwke}M*ZY1t9u#@r0k%xkN>;eG9?98TS%fbp`6&J&(@$+jed-K3m zwV@SX(E!~<5jgA%%(I$p#QzFFzq`5R%{oPrlpIKq&m7szLR13FtBGv^F85=b|JjcW zvRDZ1JdZc;NwzKs2`5LVba{PEyT;fN+)Lj7()lR=-3heJ9-8qfgbs*FJl`OR&R-hw&EYq)Q? zzuR)0yUJ->Z9G3#3Ft@?y9I0kXZvy32?GYycftX?H1d-H=w`#h-^K(Fle$rJLI+DzY#O9wBLIB872K8SnabDnLCN(t0h?2Wcwn4uOG9 z)4oS{w{w~;=M1v1&W`Ew!w1&R-~IHKUcY+9n*0CvFaJy@XQ$+N9{a_SdiTSJOBOzG z50S@UvDnb*@qpWfZycNlJadG-NFuKKIo+r0HzIu87d-)0^`NEwA5^mu~3z^qiJXK;4tCDD91jVo6-YE}@*G zfO$g@c?R^IPxz?szPMW}Aou{_MMJ$ro+_3l+Ioa6vxoIHqo2G-9)E z2K)@*7$G2vq+%MXTN<`9v)4CZP!s+ByWdcn#%yNIP=#%|rpaU|Y~|sQ0g6rIUPr>z zK!k%Piy|>7W6Cys_+}mQQq)ZM*2wEOOt#U5`v@b4nl7q5qS;dV; z4l_IQt8drbS})AmoQM96@80kQ_`66z9Hv|8M+84(73jDo4Xn|?*>TU;fIOF1HI?-R zkmuUE*~pf88CW?#_n+tKPakRJeKMYI7^{eOM`J^SNPLmpOz zEcIFYUM_H7C*024cORr8T(?UvUz}4Iuh}dP7sJKn6@B&kHT}nr|IHBxh)6g+I-wta z_?~0xzyA7buJCugL~39-D>6D74QVj!u`e8MhYy$6 z*o4b$LJLF=ZlrRR>SiKPoS&ZYIZm=+|0-))S)N#g66*SrDeNrpXwVDjWHhEx5OAWI z%n|Js?LZtcYl@I31JbZS@OZ6U_(%f7_rz%I{I`HQJ_gWjcSFK~;=2!5jzha%&Naw0 zp_%Y0C(EnOpRw-O%}qmt4~wfCfGrKo|D`96yW$kqWoBQ?6F`$G`gn z{rkWE3yp_k>TyZfF%8Be`d|P2&*b$`uY5?$1za;e7k0rq0o1RqFDP8cbbO2oX(zPW zENC?BbB4k9@2}|i=!D)~y0G_&`W9WuwXVz9GY&B&HG0fjk%cacxD=Fc!8d zP=5yW{oS*;P8!Qy3%k_-S<}|F>ksvzKRH0poC2U1!qyBR7!9omexKarZf(eAVBN6@ zZB=t<1L$ph=nMk+_^K=<#RswtpzpK|nL*k7asP~VX|(hC^o~IQfbM26nF@#^mN|+u z&d=WOOL@)ZM(TANt7XD>;&#Z!>`oX>+jKhN)uq%lPwx&e4LnWs4r1B~;C5R_^KpmSR}pfdpuy!ov? zUVuHyL_;AWTs1Kxd|DN*DK*T48}uRgezKx8%msniE9Ay zJyX5i#8GPfw1|=-vBwTrh?OuK=0iBF;yTa;iz3(z~~B;n$$AUcO>L?{$0h zfBfms^uPY~UzqF&=KDYY8k3ee3xDxUk) z0bNsIj0K>L_G_Pes1LmjpjX|4y8ZhX2lW5(kAK=eQDuv-`B3jk2={Uq@65$zpkgN6 z1aQj6mn$55Yigfoo3zUNx6GXuC~dW>JnpY*e2}oJj+Nc$;<+Z*vH89jXTIkUtpLqh zfuKg+pBX;78nc5b*g%ThBrPWYdS~$7u0MzIMgU$n+2H0&C_>)-%6% z@$T60iq;U5s0QOnyM5MhmunE&AQ_-gEXaUzXO{_5_&RJVm+MkmMUsYAa?CG$32}ZWJ)?DWUm##r|wu3jqsO5mZeBc?}=1_&Ik0A_~}TBB^?>Ztv*Ti&u1ed%*$` z*0zK6zb0>czsDKm{LYvzE-pD69{l{j{mplDb#Xz_a!r5z+uzaE?3OOCF1JGBi}M$B zhm3&8!yg1RUEHz2V$#NPT4A_~K*YqoV!!(d1>F(*`^ke9LLv&Bj=L?@TlWsv9n(zW zZQ8A}0yG6IbDpNP+U*s`U%b|&maYPPvtPCm2@VJ#600qrCE2E-)FNIIiIh*f4|h zFf|jmj$=|lBip88H9ufD{Qv+U07*naR005N={X=WATU5B42Ym4;RE2c0X=m<@Iw7@ zWT)#>$44sHl#tK{HOW!cZ8#dx2w_VO5rWpb$fDK_n2CQp6!U&32VMr$+?>jw=?Y+P ze{z%fR)FLB;SPBq0(OKAjbmGm0E)(R{Ox){U|~Ry6BZ1z+~jWBFS6yMe8VUTX6F1T z6h=8Jp>3aaJ2Wz{MrLbLTZ>DY(vmz5ITMnc!zEl1UBH#+T!+Fm!fI}X0-Vb^_1l21~Xv-u&>2LnG${m2lwS+iRN{R7Yeo~X!%m~gCBxQ^JokEA%98kmJOj}zJO zvl53a5CX8FIinpEmVuCf_OjHY%iCK%2Udb_-+V)N*VmM6Li+BT-_X_FEnVMS^PEu0 z@BHkXwRd(4_4;%(z1|jf5lfGx66UOhh^6;CG@cxDl{nW!BBLH#WWeWOo`?b%8XzBf zy#{U?I6p)Pr~~w(;Mo+=i`SL?U$&Oo{IvBg)9}A|KyLyj8lYE!Pg$n7qCn8J|2kl* z8lOfQtGdp7Z?o9(UC~GWF#x^o{L5bQs`a-m6vcD!U<1&j)tZ)fQ<~k}(F$oo4TvLY zN}k}v)&gxn$5=pQf;Pw+eeO>d?Nv5$<1e@GA8WlFUoK%{MsN%|ojuZA=!6WwzT;EZ z>k>$OE`$J=DDYhNjdNI2;8Wl_oK_SGWT2rVw!G7c$ae*Z#m~MYr15wh@wu|*ZUcM% zH_EDV5*cXd7NBF^>^=x1X3YcS@VA$jFU5RtO~QH5bH8~WPj9qyv=MD{zV8dRW-Od` zHQ9l=mB)!615*uZYdy&=aOV3v2fuf3V5!|ZW?iQ9Bn}p;cAGFXZOrB)B0N99f z0HEV+n^{LYxP%w~M0U*nnXSoiv4+R`eAo$dPZmdI9<2VG+ zn}GVE>-$*)dfBF4WNF?%XTRD|8MtVmSEkvU?=(QKySD6@JwE(hyy3<1YosyLM-?DO z4$AB8tOrFOxd!OkdTL>7ZPy;>+kIAr0SVJ*v=?P?udpJ6xw%(1m>bt_ zv97o2%d|gBB)>i1Pp%>-#IiVrAj6Z(0bOz;2%wv6elevT6iA6VXZ!*_d4PQ)34)N0 zb~e3bfd=;(x%crI42A1}`QP45g{v^=ag6+Q2?3zb_Y}T*w>uC^zyj>3X@W zY(#M=X>48JrNw4LrzgjhMlrijPLEHRI{=N`ScSmO$NzYa0O-rjg2!av7xO=!zeSqR za5xq)?+$1*nULF+91Hvq?s10h!|$Ph^Em*z8Dp8*ybYk20l2n)+VL+^L$3lOS-?Ur z*?Te3%>lh!VA$V;is$HnzMsqeJ^+f#z}|H2|BI%|;tTSSICFapHlQ;Y72?c`TX5aI zD0_K7HlUXYG-X1CS+^`()9mJ!ZZEHCHD8E;WD=z~83isXYUSx&b04n#5@9n2DGerc zskSC*H1RjiLkzg_>0v{n**Slaa`wsP?l@9|N zQp9~ChP~hMX&3}F=yf>XJf$&p`Y@5Z+X`vif1Wf%?#J%^Fko&!UnaG!4a#O?Vhcwc zvWCijEX6(!y--P!xbo+jQXlJ))G@{-85r6+4m|G7Lh+@T$J&(wRi9IIN3m1W; zv-Ovw4;SU|IDb4lGI${ir_A|xw+;0Jsb^1P>5pY zNw8%Bsd4ivb6!Ux5f<|~=eGyo!WtAgLgIs89YR63FC|h@{*;s1Aj8~h$!2(@kVOer z%nw!}WCC>D4$bCsHt{1~eK;I&cpP{c!vXv)c}{&RW1)F|nfs6t1t|FAb*USS7|=1c zD9dZ5E9F%+z&Z4|eQzIPK7YtHb$u4wt77?^^Gvd)sx}W@pQgFqtNMR(KJ;QP_u}T= z6wu2yeU|E##3&k|HU;$R{&%^wi=b{xd{sbtxDP!&D9*fWUiQOP#d0^GqOGspR#{)R zi=ZfJqwQofW8XQ*a0YxJLd6JI$}$@Gy9!qff5=d_t@TZ;X&cizDyVT9P56-E3uPaw zXov>Pjp^HH>>Y0x)&^iUU~Y&~zAqvZG<0Nv>-${_Iv#81-JnA~KV)__Oziy*{N^t8 z*e5UTA|0pzoXddLvA`UD=@hjJN(4qT=B|||-hg@$&`t3Zqm>#hoOuShKy5&__zcGu z?a+X^SsQ-$3ZzD?t$8NcieW`b6fGgVZr$#d;Kpm8r|M1e=!PB155zY~#~Y>+s>p2l z*b!3QBIF$DY_exS4{4J~N>^BE;5$eE#!6#~=k)r0CdI)gkL+=7=F=(?H^d5c0ek`a zyW2a;^2%teZRgekCw1AZ?)JMJDhJ;>3x52pfMnU{(y432)vqxQ0dyu;_5up}!p_Io zie`7T6MIBMB$)AG83G?;#J+m053;5J;|x07)SA(Ljmil0lK~C@_w+bKv*6P zVB=GnhJWb#JOg@(hF%4xWe>2u`85GlyB@k}Z@)h=Q5HYD?{=iVGC(gIqut)&K6Hcv z?Rse&XWj(R>*n7S(5nQRvec8d_P4sbWFp*hI^%SzAWFs1Jdp;LG8+5B+BWSQKsRl0 z;uT~hv&crqgwB=LU>?n5&TWSHR)TkhWzJ!0d6E|aaM9KSKjo65Ug}am=y4blYL@pp zFx@*e8h2@cob9N+?g}Xm{`C$_rFqB|+H(N{&dy{GivY&y|+!{Ck(MU$_-JDAY*?F}>F z7wZ*4KtOw(Cx9~p_St7HM81$lqal~_1woFP>^Y$GGnJ2#(-<3$gYVEFK*F3Z5vsWj zCmhnJY9U_I1ZGZ?f3Hk%7!?>=edZMm(-D;anyzJxRsK%x3ehXhYCS z+0PyX)ORCJZUct)sN18_a7Y9A-#vhFMyKaTG#rjNj=2L9G6-0l`qgD-yovY5eK3Fy zClAJfaclPn#b=C_%4q1g#;o5aTI>Nj_yne8EVrElvH@zdZsu7A8LX(i+XB}Xh~e(Z ztGyYm9p`biKg(~=0#{BfLtmrrm>JuA@9YpaSK`Z2CU-kFQ!5m)?70SySOUbdFV|}d zH!#PiOmbU?OEIy#eR}`?z4++!P(-*OjJ7^s&*|vsl(lFkCHh_d8};0IL*F28|4Xjo z2hv;u;$E0%CPZ=_$ETmKF39hp5X*+TJ$W9%rC(IMX5DZ;;`- zrk=aQ0B^=+tSMNNUS9wm9E1K~OhLa#J_JUToh=K~u{Nti0Z9Y=rvT`6px#D9FKg$} z^$SY`<~=OAPfOY3UH#%F_y6-B|GYP(BKT=OSfoU(``GQ(X_Hl;TYMnzoo97k)`nr@ zR<++G@ya0ri2=N-HVo;bat*)fN$Dm`=_CauVY24{>K6Ye#LpU00Wdk_Q`%-rv zRa`-;V^ckfzjVZx9gwiwiyE*QuSuHIF`41=ifZP#*O6i<2Gk9?&1_D+VU2yUTuZKkPLIJDTKkM^ql*t5g5h$tqUk*3oa`6xe`ZEI zAIk}k%qB--pe{7x4r~4EO+>3CqItMxjXhhXtd&EEfWN*I1T5$w;~WGMWNI{g4YY^- z1pi|m$SLpVshP1haKx|>@&B{;rcIJu*_GJ!Ew+rvr8WTFP0~iBQQtJ&^+Eq#-z1aF zWX2hBMnm?-CV=inq1Mcd)mPa$_g;?|o*v5Ma^^)Nfy_XcD=cIE9G*-1zB^S+D1|rDQ#GhWy;WYVjJ#PSc4Ao zQke7Q;*TyY0CdV|ng?p(H9RBU5CzB5lA=tcDd~a2!$qkWXds+g5V^g3)fU-k4GlLk%{cOf%_9;{ z;)9rqpTp1V$6(~8!M#^L0;FO=bpz9#dGTT=yJ*UY48Fg~fU4 zYswJd_N_q=0hFQR4;|~FfI0-=-S7KC-r+ePdj6s7>7IXR`|ldiL*pAi4*`18sgn3n z1G{@5@*Ny)GATZTzKu_eT*%~>OdX>JpP6VSvY^8hp&c{djD<|bq!mv z)7|*(K0j&<>)hh!Ll50_=|T2427Y+#Fy(Lx&>M7Gs{xDjSLxA~jmU;da+SPVq9$F9 zHsrzKnIn<|FfHqfUGpF!^Vfg` zC%5@V@|^-cKG!$eGBwIHY>#v9>R9qZD=KhqTuW{dB9(D17`?$W#FP?P^&m_#1p#3j za6Gh59XbBl`9%xpP#H@Gv`2>k<)MJ~P=jIU{C>RdcK6+HXng^o-RIc%*`^DYL+8HF z_I}>`p1*reteL0w9ZEU;C;`2@&^#1WyNlSt!ZVOojV_o z-$VQ+=!sVqsnyd3cD*U|$bM9{_r+(T31# zKJe1v!+E#1j&Ka;iv8BTx3-m_Sq?q~^w2vGA2$GcYb*re^*sn%yVU^DIbJSA!Ww-y zV#0+fG;G4Z`}5@Efpo8P=4wj6LNQJaE|#rr^!NZ%h{zy>4?qV%k||#ol13}tHz8P69IjmFw|$0$5LFK!&( z2TYD_^AIo{^3aDsZ^&DI$o_rXh92q=Xx_)TdC1({=N=4Q|IqnDeCWHraQ*H()^{Fq z_mJPvjq^q8*mm~??e2C%IsQ|^FF2MzFhl1b`u-TWhc~S67(*WV5TN%l7{c>BWPbYY z%@ClMF@$jl*OEZj9<{y5pWnP?Pig@A9?qM`vUH?QA?{xczK0l99=)qO;a?qGB^? z3{XdnIb=lDD@L@dL7dpe7)xSmg%jh;sOGe0#kP&GBQb>VcX8YDQK!NAJ&&AEOD3vF^FK z4RZgjcaGo*NRy}#(EEH_#(X|dTfSVaWRy-Q2MZ%obL(3+(qY~CN=06v8GwCRhi+m# zZeT=lDoqy4x+rC}S;@^>!|CJkREcvtt(sVGAxT?HnT+X?`~Dc48>qORLUxR}K!^r4 z2e>A9=&&uZZC;m>Mv#G>kX$*LFC;^H0I4K|;%hZVyQ!A@fXT-O==U9SxXug#UN_|Y zP*5M*eh9aQ#y52Qq5X%ut(|V(^P>jzK5!YTvmVM}4*`1LIZuIH_q(CPCv)T52m3*K>!BdNh0uKvz|;eUp+dsC&(F2o?@< zluiw5r%`8)#a+F3u%jH%W0KuQBdEvK6n{alZU8!J%)xL+xf%$4=Fm$il`JM>0y?^* zBW%vGC16LZ(jB_1dDOr?bRQeGot|k~5&*sR!Ys^2kFVIaB()HOo~e&M1YhTT2n zj_*B^;pYJeAu7=|mVCYlJ~r=RsNS!KfNOf=s5~I6-w21Su}7=a0T!@;Ea@(I4=HX0 z?O*B=#02e%90X+kHTS-0K(N$@XtmnNXf~7ea?5At8vV~VxANzI{%7o;4$+yXPoJ>n z9O5&@W+&TbCsCcy^Tx5kERV8OR>h7&GP`ZVW-%Z@!mGbsq9je5;q1yrYvx-mdR*;( zfrV%fYTjeK0ahhIiCbvV1Nf1D2e$-9<`{CpGs(sikx@zy9bz`4Y<2+Xe(!wFh5+F{ zUg;^&`Yt{6?)y0emiI9LhH}V5*FOZfLt}j3`5)Tc+BrSQNA*QHv`$u^-?ysw^Hpk zQld2{q{P}B@gC3-mQ=CUy&a=DCD`PR}?bkeNUY{s!P3kCfCz@fqY#lbW76 zjtQkVl&(SU6khnF%S&0HpZ0VrGt@JK_y%t)MIKehIybg`2Yl#U6mWU23R znT*e5xd9LttWUq)E#=A6r*i%FEu$x2eEx;JeDzAE<1x7#1#|q+m(Nv<2xXFKLP8wC z8+8f*a!SjtRsTJXQYC5D$ho6>V=qgL>-B4ZGXds2?=J*}_)KFzk=&wAAjL6dlZ;h# zCr+dWL2fpa5!&*ORhiE3cgTkr0t3v?`;xNW7toJ^_t zJzoSNjp~2}ViHQ10NVH)fM7P#)|sl~?tor%!AE~|06JOiNhWnwN(46i2szIYSh_Pd5sDTZpT`fC;^SpG&`o?Z|&l}z1_}m$3 z&>PEy9y+dRV}d#WZHNd=oFB7U4OFB%^Ep^<`P<97f$HI7pj zEJ$%wfGcvT)?3L}8`*ADt`iChh7a#3~SDIXNnzOU1OlR7NBQN#X0P?HFoE_IR&#A0Bd=5q|mzyzI%vz+{5p2OgAzJ>L{-Z`vZh>qBJb_TJuPov}85|>?U<- z+e6^zxyb?#+8cW+ArzA_Xqfi2?e^W^U~se7dg;w^QrT7o z(*QW$E-LwKBtQA(D3P1pPP@IOGbxfpUhhydzf}U}>`dm5&gJ~cBNEX3vIQ$Y+;FxTgFt*(QOX(+>uJL0z5-6uc-7`fXvqG4LsaY zq>Vbp@Umw!scQAuJ&!)k)XO8O4WziSHdujIj^oWo2*ra4ht{b=Kp&-+7jAq+?y(Ir%r)b$z|wOj^6?305FZ#7&{!Us7a#kO3k4=h`A^4A@Dlelcwm! z1=|u-J!Ebko&z5KC2*mv&BE7i0QhrH?-v9?;~>EFa1R|u6@D(Qzr2s{PK3#>9y#Rp z6L184!9A$u2#f$fU-vopV{Hw9J*^OKkDs@tNzTHvr)(^YB*wXU{VTLch1rm5hci5f zai*n^%iCLmEh7!atlyTEYd9c6FuvYB6p$Bzn>Q7uW6N`e-&WhH3} zMYvdQi>@Zjf@83jgAZw_J;x|`uR z<8h`7W05PEqk9&}ZxaZ|OxWuj$GVuNG&n$v1DNCd*+|EM?;&CW`4A|AA@r^vW41@g zmG+mNwZuN?brX1v-EOLI4(O|5tzKEA<5A+-o^c+HHUIB_>jFARXFR@nb{w5OGbDF` z#cl=#z60?3GmlrdDE9`513C>VH#p2i44*6CpZ5u44p`bS9^4?KLC|K%gQqM2^e!Oz zc^tTla-V8J2p%bg@c1=l|I|Q26sN9`gI9$%0J}#kkh^9n901+=2dvgB*^-ftC=a~% zn)j1UVs-_?=4i!=F>Uj$djBz$~^Fl(F6&Vg0n3%D1;m`H$Bx zWWCO1p3P)7JCntebGdx_gz1HrJ7TJXYT&7%(UsQzE&ww;#(g~GQ)}>$0q`#04}sQC z4bYDP_@ZBcMNG(PU7(G zyjh6@W>81pdgno2TPBBf=m+FEg!psSjQ9C;Bh7zz58a;`_oOk80Q9^Fy4AV4!kRI? ze+4{L?{{u&btb{z?bK>qxNhARHn*7Tcj&M~qWb>ypB zSiWQDs1Q1@N;Y7DhB^&K1IR5@=1kxS&&`Ty2C&f;%nNAAv*VlAn`cwijmNeyE-+4j zIW*^S&6{e=>yEYS48KP?8aM%)x{z=Gcq6a2TlvH7wd6%3vt*(|GqbVG9-Xt~jt1pq z0<)lv)KE^DypzNB)ZaCr`|*ZA^w?VPE`a?|gW}ZKK6J?aq1X4m+YjA`q3`bv=*NI3 z>~?m_J3M9-40-57$2_G~9(tfdzip8JAM zFVRS0Z3x=J)mY%+l_MvOoH=Tbu`r^Hjjb&iRxKqibD5pZZ0=kdU0lh+1Ku2)K^XxRvO4BvBR0GEv z`=YW4T!(DixR>)8AA#Spl$#3Lj4`S{!MnUS$uUGsVw_O>WT$!DUFA}=JHsjMsJ z0yXaBW55=ZMEeJ@WKPeQlgtJ%H({GfpC#-M-FGE#W-N0n@=`{lu`JiOHs{U}fY?mL zc}J1k^KX~3ZbV*gwsO19QHMmkV>F-2#b=LAL2j!2kx1*<_5NF=Y9Qo31R%$NxDUwR zD>XmO+Ybi~$ zouSPt7x?LuNIj&st{Ndv>r{p9@ONJnM(~VH*WE+D0Ce8Npa~1Wkl+tp?|j4k0pMV< z!xK~i84cynvxvR47xNigeFDtUKn9^y^gV}|3_WtL!vH>2pd(m8(Q%|9`4G(gcl?`7tbMG#m-MzRFRnmtgu5{8Zft0b7js786>GW@ z8nGA$%Q{bl+##~#9|v9D4>Le&^q=qK?R{?WZ?W43UL|01pNGdWqS>qkbieKpqmUyG zLE3+IqXFuIT`+fp1%KbJuNi4TA9QrU!$-@;G-RHbbg=d+kEjdJ@ka?IU2z}lI-*Bk z6=)CxH8>ojWcVJWMSKtN=lh*xS`JqM&?mCo>hstBAKb^Pj$~8D^3Cc-e*4Gg^6GXi zlXxQ2>0B~IhR$cQSS;wBBQ1s5+h5!F59r}@Ib;a*83cX%ybIv}DFOPiIrlku$XxLG zd?=uILGOnK^uDsMaE$K*==bq_hqn2t=g@bzuO;8^WVc%KUxEvkLDca^jf_PXKrCAD zguVM1!?1vosDNE z1A!W`?rKOzgBkAoAncBs@j6!Tn}8mp_xe_!r#Mj+ISa`b(0H%Z7yzK-IB2!1_2}r+ zUZ|#jI_5DLjvr6?3Ggj!b3iF%AwhScLDakfIbAw zzNm(`=RW(q3!sO`4M}l(&^hey?qlkUFdX|X^mU@DCt=6re zl3Hqx9Ka1wZ^=X=tp7bfKW_n@a0ze6bL4R>d1PAf#@Z&hn8yiFPoR|!(HOR}jJfY@ zlu;}OpU*C51U;0cjnhPC;}OC9j0Q#`qhwD&L(ZJXH$Z2o7X8mbRC6$g2g+_7=tLGt zwml8#qhxQKw7?#aAZsJ%aj-#H-mlTs?|q?Xp5IFH7|k%Pd+hE}5MKzekCWp3K8B%h zoDUI;_8I8`bg;%lL!#>~?;6OkYR$Mu^FjlnNUaBbkVAJKEg~CHtQ-L3vHduRO1Q*q zk?;Gd_W}BtC0+>qHv(OK=H79y%o55QO#uP8@!4*3DIhRoks&-oELlTY8n|_46adU| zT$g%9h#h5c*nYFxQPP!dR-rZr20ZG{Ic{Uk7Ztf4H;6)AEac^CE5H2RS91OGRz}mA zJpTNdTz>XcpsCbWZ&(gpOZ4uSLmzrShX5D*4|#!q%78vJzg>f6XueN<-*+E|?#&%Q z|Hr@Clj8aSDr{fZ_x%v4^_5+O`*ZdX z;~xT3KmJ4JCEWHD$otED>e!G!b??i80$wmcnqkP*4Fx$o>>JiV)5A?;Zi|}l`Fz3c zHk);u_nn`exBaGl!FJX!d#Ia&9L|m7;FDTAOor4GtKCf^GS_F*iGcZ@!CkCD>MG@D zpFfj&wUP6)seJb6icI`C)tcc+Hl~N#*21&xYbs^D&!30J+1^Xn^ZUmMYwk6d^}Yr3PTJcR4V%a)Z$x{bLmke=kZ#jLF5{VO-frZpmv80E%|@O>@h&-& zUp)RoMvJkGry4~P7$>|3nuEu=^e-Ro6Fw7t&&M$b$w$=nBE#*6z{sDs@EBc#@jmB2 zH9LLMsRwIrryu#d%=D@2d>4QZ_wnbz|JI$KJNR>7K<@(vUo=jE(#Hho1g7Bq_yp*> zXq*D{yw;p|+Nm>kK;OK4PC$3EoBzxFEn1Xj%3Q|+&XOT?FdL1iRmL@~=TReHeD+jiTgdrzB+src zrO3A=zTy0ui_h9JEh@wX`?p@Vbk5Zr1j(^(FSuzp>G~00MPDO3)%~&;P*^R6tjyH|Po| zpi?O>&Isr`+!u)MfFWm^*@zgphu#P1dt<~RNg&G=rkIC9P4n(48OxgZQdVgt7s*u0 zRVm+GujM~hOZoR#Z)CeJ<qdTASu>i`A=AWJl4Pj3Yp*aqglu#cpav*}D0 z^EpH95bc0>PELALupa%{<0~dd&&R1;%+I6-2qkEkF&5Op1N<>Qe2`b?0&iWql2}8& z-Yt#SW-4l3K=%dI0aih9-)+vr=s2DSy4?WcyX0U`?RSklR8~gkUUGO2H5hc>+p5fiuKvfWd_eYFgVZ|1aLY zV%te9cq&<`d1&lIAg)XK?6c1akn8n|EhO>X5_<0xjM3btd+|7?d%_IWk4F@a!L|T% zbUX`5VB@rri}`{;JsFSK1O*~6kZ}blqV9ZgHbb{+nIuAmxR^~k66V>_dCSL&XJayj zIE_fT(`bTNzw!{!Lk~U4_RTu{-iOZsy+T}{5vK56m~}@7F#nw|wUNm<=O{NbfgI1X z`U2oyFSP9Y0Nss>*mBt6LU#b{rg-OL#C^aVdqgF*vN?PY;PN)BI0i^%YV7FIJ$2xD zMSs7-aAB7*?`%8>bTh#euyl4gRkHjEvX z-)@(;Mm^0>Jl~?xBJHvUV^USyU{COyEEYtfdG5H#yOj@ zyxwf&w|{&ozyJ27Z1WOTY%)JTlc!HUm&Z?^$Yef~*y`j7>Kz@6hl2Kyhd2b1Lm=CY zm^{=&_w$F(NcV4j&+aiG?9NYj{qBAr4TRj^cm9U%S9tusbGc!8Y<{{`Xwgu}{l^aI zVLx$9?obZB3+{jFfZmrwN8LEsy#VrNdCi~QL-z$5FE)M#fWjjOm}7yxxVY51-tC5e zuPjIEY;6a0c%&?Ai!_`HAYi97Q;Gw?!NZ2W`eJb==Vx=tkP}67l33`eCrKn{C{II~ z8oGp41xwXHhD*{&#X0ZNsA>7XUi$EkKdc6z}hDgvLHV_c85L1^dfBFff7=KVECH=K!d;Zo)oZDkzAq zXoDY!3vnLul4E1qAg);74S^$&)WA|lefSQBP^?uKh$S%GPU9ic?s9}@NayNtG-qz% z)PR=&jslGz2;4M?3SmYeQltAocm_f>nB^py$ZA{5^Ve_XKVH0$SJyYPMOG*q$@$fV zJbC)LTwY#EIvL@@hp^yY-`@w2j)9}!vmrnY&+!S+?~)8p-Ke1mi357yF+yY7zrQ!2 zp9;H&C%fyx-z9Z~+YFJ)`pz4kZ-^8Z0y>WM&>Z?FK;M(%eBJ@*2(vSHe)EQ*cYLr| z@2p-Iiz^h?n_1m_wC{%HA$Nitij{&IaSu;>zPUCcpL^ka22B73bEeGbeN@Yvtw1#o$KvyA z#}BP^PfIvS&5sdoLr}No?hf#w_k(T0llOFo*S|ADVmb3rsVoF#&rv6%%qjp5J#-%1 zQd&M2q2c4>=!WwTj13x0Iyao_w!Cd$$^{P{fR69|nXA}YO`qF>fF4P)Elq1ZWsmY4 zfS$%u!n3v}F$%^gqqFnjX9&a)%(d3sOXC<{XH)`u_%#g(R2(>{gD6Kp&$qHh8Ujj$ z(L}0EEpL`<`Q57*@|$nIkvN<17^nbw^z^Yjdi+eXsWvHsF@x5`AM!H9h2j3|HB+qE``P`NQ5zQYeD#SQfv@80kq6QJKGhyJGy=+GG;2nG2ncsnRL!~f;= z>$Y_zwu5j7{+(FoG=#xD?2I;_SQO!{<6jrka6rei0nd*? z;ItG+_%60Q2Fk+jo4*_aIz)4nn}GBCm{I=cKwA~s{?*@WHw^q5qfy#6tl@l=3VvLC zEKKiU=<|eQv;?~_LSYvWt|5mx^sWdEbm|q*u}{VZETxoNO+(jxD>ggowWHN4 z$dq|eu?!6v5syNmcAbEZT)hE(Z4n|jJOSALLA0POv@{SQb%yIB0K9TA$bR1yvW#je zY51ffD{L3bS2u6uU%vdER87XRw=5gW#iL8PxVn@KRT@_1fbjc={CrG+-o=j4xZBV9 z!@%=n54jIr*9Xa=-v#O8r6wOMp!>MOGO#d*9$G&>$=GKoWO#vA=48rR@YDh5AjOefW}p#*J3{)?nbuu% z8Lc58GnVuDod3e31nCW()&TIJGbK&U@H$lEkUPZ~cAK?4y}XifDl$qFSzOGiVP3;f z$x9j^^d8ao93XFmFy{4>HGv(HwCJSfpyhdde{KlM#!Ppxqn8LkZRI>Q)b3!6^v@<% zG9io>2T^Ch`>{RL9|EC!%Sn9L-qiP@5f;aS<~HgX@5OU;p;Uqy|d@UME1jCbt7CZLY+40pghnS2tYcVgqiLC_AB1w8)7kv@Q zcUIH|GU3AFnPLw9CylY zLa@`H)nYvc`Uu&bG6=fgb)Vgb7!#+)ad+JMm-jtC>V!jfatQEPR4ATtqSpObxXQYUP_GL@+-fDaH@C7|tz}cL1jG_2#la(XaA!BK z&05ltl?oNwdmP{h&;+{9r}o<9&68=a>HVl6J=%xV`HbOS1bKAtKOaUt_TleF;;B|8xPgP8{d*V;AVanxa~n$&IBv4hh-)^RRyxo#kE_8=m9C8-kKKkm+n5Hrry)d`G$npkGIFvtG$^ zxt9O(<+pOZ-Aa{>WHvgJ#o1hb{)?Z>?D0Zg?bb3&rmdmp>lN-V`2i@|JfK+KebfE9 zIt7ZS)`y1xXy3LagrBTSA)nn&*|5tdx9eRXKy-59vo9ZFu=I^@X#Ed$So+2ouD`w4 zKcFKJmVEZzBY$s>%|-W|(R~2@G^m~ibZ<3z3^ax&^dW%WcdViP-}n4Kc0eDRABbdN z8wgx*y#pa`xoiP_mESTqi3bZFaR}&aNK&EybSgQTUz7^yY>|q3^C*^0ofFVqxeMNW zYWZq?CmeuIO7UuPQ;Nh^T?#lJ&)-3ovzL~eVCPB4O8WEb^W(RmZ@F(qR4k0{ zfKG#_F0_4WW9NYpiiSZ9qa!!oEtPWxH%%Ml0ZEUNu~yRPWF`PQz#mOtcDPRHBQ&wB zc3Y;Ne)DQ4-`-rymZ>6eLC)l}&p(sd;|sa2wsICLpto~mhLjWapjj~Vc?c+XkM)p! ze{6t0G;e%9?EW4zh(0u+4;d_7z#jy3gfP3GZ~=lu;i>PtfIb8ur;l~oqaHf;eE|QV z=l`w%{n*(1wCck#zORQqG-oK~0RZwmSXlF1Hp`XV+}y}+xfTGr=ac~^2z_fK3@E^2 z0jmX|1TfE=%0N^lTH&dqEDkJRFI%IB802tAsfMT#DhJrWJE!NJ7bFrPe@?A#sKiZ1 zXiu%Va}tUgnNBjfI6s#u8n;MI_B)Qd(V)2-+2!_w!j1H+x9~PIu<32hoK>me73o)ZRmoBZ^a@0^G?8s(rA0_!ZTa zz`b)ZLns1)ZRcY4HCE!jxhmxi2!5Y($uH3t0SVSRcY zh!{+=13>rdasb8khwr^#S8D_~Ik5xE2Sx%o6R1}(=~e=;rIA`dXF9=E_cY{@vdn}mS=_{n2AfBHzq z=QC-lJwegEF)u5`?|r=@-UpQ5XWx(ALl2+3`-1w%4(Q!Ee~^dX4{nDR^4*Ct#_K?? z_FVyW2ylnI@*#s_$S`Q8IFcRfbTw~HPou2a=F|ZlVRK)sy-bav-Fim_EzP@|Dq2%B*LZnxA=eP7 zscJc&Ph|=M+;&SZeSS7&jy@YDa&dk^4;_GxCM`${JD?}^UYNz7g%C6dxG(@HH?sH8 z5!81N-N6BK(0#!?ZzN4J>_2^EU2FQjyd!ot>Wx= z0(#s6I>+W=dxr2$xi1nacD3xPf?j$7-UI90^|RWh^4pis<=20FF1OoUrlUDiL>G^* zWcuhrrrBgqP_(E-NJ_j9F#Rce=*K|3J158H@h1uBr$O`ma_B=3DM1c_;dK$em;{f>c(I}z(E7C(% ziN+VovPZo)1Z2<@W(qNxSY$RDlN5)*hmPg2pSOdFg8&JB0CSX=8L%~A;%ogz;zIEP!0_Xa1R)<2+|NPY{MzGkiSO(oQ>||=>_q?@Bqgk zB+)sbvjhv(2Nv?rj1cEz!@bn^2`$Rh1LyB{@fya4Jd5X?@0J^J8)~H~V0J_9Ty(Sj z{(ep2TzfMWU!aEoU5$yohh3rC!DU{_`G8`&<`vR*Hx+U2r?*KC69iM{{; zAOJ~3K~#A}VHdgpOXh$b2$wS?&Z-qzudp z4uQ=VLhY+w5zvvxc9y$)=m2zI6vD;9@8>pO9RRvtYY6E69EO1I=jXhU9JnuQJ5Z|Y zbG`2CNIKLP8&Ql=%e&C*Bj8W?M&17H$-FMvQDBg$6 z+kIQ*wOS&J857X$K5#oT5`CW#%tNEg!8lylJOU7U^oqELA#*i4G>4Dlu;k1D8F_U4 z9b`8At5UCf#y)D=Nt!c*&b8p(Q}^+}41|}DoIIic0CY5N!SRwLlVTgmo4SyH{pPuR z{o<9R(O4#vGdWw#W%2k@vJu++X8VqSLF(lbpg&BN?V$z=w*Sck`d#38KT_O70rVK~ zy$g5`S+{*-`%oVG4+ZE|=k|FY>h{{bc?K4wd?&m0TDHq2mEY>TU~>-7ul4~t^4Unw z!jnO)8-NZl$3BzMSmLpksBzKEReu``yO(o4zM2sbS2wq^IGb#=QW`<)<=ru5kB zd?(w@My?ifIbWPnLmuDLJD*IHrEY)@Nm!J~;kcedcOVSCW6S|r=;&yMvN$N(S=pKc zx~Bp9z#RMc0lJpssV^Ib#QW;a5&GpgU8mgG=$^xMQW(KCkf8O&%MA!OTDsRaLX#2) zVN091Ccmq#;aI#U=6}P;^s=mI6w?rMwYE^}9iWVmduZ_RK6@uL)}imqCcV!>ShnWc z_MxX4{_LJ|_xl#~?eH8!51>aVSgW+{Df02~-ZAG@1N{URYAOf70Nu~m1$3Mb1X2fd z9}n{Bh+<(sG}48j%{o_RJpjEaGg-$X|MvV_`SlI)j&feyLm!(|K^? z&yAI~tnkP}`pH8-oS42S!YK^;*a5wJJ#7yC7@(jI-M{Pm*U6?nDc$3^Fv+n=JE%*% z2Wf5yxbK`l5cLSh(7l#p0jTTaljdSjd$A>T(=SMvP%a|*nG{PyuC>;r~E89h?Qv;UgtrQFXp@CR`(to;&ogLy(DK-`TacrF2F(sE1?iYVYUv^Y|kbD=#%$?tCa{21p7xLvdZzP$` zJy2-Me&t-HvF@AyLjZD{+UZf0R~nN#CBh7T}?PJSSr z9AtC6uYle!?e=%-(+yd7x4rN64b9WBF?5eVG)F_{A)ucEq_Avl2+;e$@4E!_zT*!8 zyn8O;gogVJ?f<6+=yxIzqM|BT5G&|XFK=bDULF8CLBM*LW4_sGs!&!tSjy@Nn;v^0 zLyG;N#SWnT7JxpPP{|8~yC+Ycuun9;XDu}t(=ZrNCv3ok->()68K%68A)xbkYRen|I<5yKxe(CFDXA*zyl;zIwpAlvzj`CT`RWg{ZBn^<`nil| z6S;c!RNMSAEu}^$?jr!5?_3XLeFF5ouEF;O=x(&0GM@TC{W}NrfB5^qy>rdsqV9lx z3#e#*XQ7l`^&$Z5~Q9lP#rW6 zy@q~yK*IA>K|5E8da`a5IyifOdI%Z$^W*P8XguxAgX8s^jy#+ASlJyy(p^Az4_yrm z6N4cku93n3-N|-4wonbkWrFfFdg_H55xPA<8#U`NeoR6ZDJM$G)>0J+%hyalA(zew z0MZo@sEIRqal4jZ{_bn}_U)~V=jSq6oXh7w`+`l3_>9N;j%oBpjnq8f-dSEh0s6-Q z=zSpHy;&a|(7Ovp*8=Q*kB9ga7!3h>pD@A@xSay+AwYlVv4@V=U2OV(KV@`$Xh82X zrjCJ7-`pVN#g^C*+t_XBp|6%VQf_uqR|Ug|VaXI0dU&N+tnhbeQ~LtrZ9yra>e8kO z^w`JNDpkF40MV1jkG0&X(q=D|X^pgD3p^eW<*-e$UJ>Zwcmte4dW+#AH5QVrwlbS3 zF%HLJqZkj_ry|)nWylT&fRnPY9Ju`FG*$zEV?fwEu|_6s_pQ4IYq+3lh*q}=d!qZ# z7`M**z5z-ch&9F5kKDnw`+QN6%!~`3BgmtNfDRz`+;w;?_s|bItpzC&R4L#Z+!F1@EhR@%Vmgz1G=$#euyQnek3+)@+90k2Ht! z1lY9==dyj-fvwhXyhZ^~qYe?9TFNMq+q{uqef@j+&F{aFvWaDJc`5V9kJ(Zc1}OmD z4Jte@+DJ$Zp78Ti0`$Hd_QAD6C*vasxrfjAeeVUf`=Ef{x1jfh+z%h0L+QcpF&+x& z4+Y#)U^(<%A6O5ae+VFl0KI$s?;FtX8f2%n<}p4Gxuaxld2>xbueJczf(lv=5DJ*O zSb0tzI_|E=9Rd!G0C?*OYRDH{ELjS-%Vn`x$kpYQ>^57e>Mhmh03HnER}~Eacr9#= zS`{*zj;H{~wy8XymBnQslf^QfjkyoJDeugMdUO!slWC>^kN+*??0}BN7~QkI2Adwb zcYd=lwU>=`jieUD!=@&-@DRMrLyseGOrz~#_2V+6jT#(*)_mXd)4&_F8vPK^J*@9q z`A+BxpV4@tfa`#+W83SiqwLQC9ow-=0qk#M--kKKFy!v{JWdb0g*lizI0De|GYve- z>?*&(J#_T2_m9s5es_*RL0NgS^jf3CMH*V-h>({3h2;JFqS)?Yj2^d z1UsJB81OnCkmwZDnWA8QyBacJ%i~?*-wo7xo+cvey{IBtHzHrXd@aBH-S6dQvy<6k zA&-9k3wiYD5jiF3>+VJr&Y|G`3DAE?Ko4{FeV~5IxcXp#ehS3;ax}*Py$>KC0_Z~k z`!3#cAHbeE&W8l_zVm*cfc`G?2htt@9XaRSdMUTpZ%K*+prf1%UPIqQi^awXJT17n zNJ>Bu+pKSxFUR(%GshUw>NJTGYF&>rH5gdu3@O*?l%aM2E4=kds(*vjEA-$eS;`iw zO;gGw%jA51CgVxQysCPBCBc6*hLO-n0~Hzr^j1q8=fheZiA*h|Ouz{}S1W6BE%iP? z$8|e{oW@KLa(D2nBF&+viOSzPDbBr6l>MCobdJ*iogs0Hd}z*IRmQ^o+h~ak)mTcw z$3x>R$b};Z?O|T*>mEA$#hbbxu8m%H(3r*9>Fntplv;&=PQXP+JM(;4_V*=?`7_ez5S{wl$L^trr0%}C8k*nl+(ZAzfB3tTIrR4d zbS}gYo;dOG@YsETv~Qd4guTmg!r|R#|L*17XP;x+_yc>NV}zcH|2&jK@7t%lz@EB( zJaEo(->z;6=pe;4If``9P-5JAO9$Wu&^7`O!7Qlt2BX{;?@@*}mlG+rJL z6UL#8rlpUpn;01WS(QtYqP=O53pN57Jy(-n-7oO_p4}mMy65Zn+4IeLr0q#l%a7_D z?qx(_Z}|NRf!XibF+leSi1(m(Nq$j9@^DB@}3~4y8H**hPh@7 zxeoz)IvTZ}wa<;8n`5of$2{n<9+dmBtj?kuj12XV;!xHHK!-u$CC^`7%Xm7I-DpBUr&?mBktW<*Cx6Fy=sTZJA@}buhkgpsX?S(Zz&iKp zg9CaOSbRY_{*atjiuD)iLx+csa5VrOA$I^e z)ZW-uG|>gw!<#sUFO(jt#ot2D(G}CwGi?ay@Kms1!aK*gz;s9GU1|k9fHOs2@UfDe z>1;|5{cNn=+G1(wp#!{Aipq@TYzk((0wmi_LagRY4T8GJrH(YDitC|wY920HgmS^o z*90yI=J)~*5L4bjD!Vcerm=Rp4oD%O^IDB`M}RiaEK`6I&T9;J&YxZ;_Mcil{g{`o zIdl!VyNB+cJ|Y66(WJdUTKc3Rd_R6X(YfgYdK;d1F(3mW&YO9oWX}g;D~L6>hCl%5 zp=a$Ly63x-EVIbTzC6~SA6`e3w`m+VN-%Z@dFLn`D_g6wJ)q+r!`KS}-D~b0(7k5d z74E{ask-#sxZWV92h7-TK-YOyf*n3ZD?p=w4ssl(M(f%eN);#RSe9ii>#~vSZ6&|@ z@+F+3(m`y7vXQ?m4>61-jq+%Y6(S!|hLj^?iW4Z=3g3YU}RbcYUXT|5TlR zxKJLO|2yV;=MO^$4oEu?ZNYt5y?rZ1zLC}KjoiF>E6<)j)=>Oz$HplDX6DXgWxL-l zm!f4=>P556X_s?R!nUXz9?xRt&XFVBt~dNUdY(fC4qgeEMZfssXL5UcEoD*2*%-Cy zF+-3lPSX&u0k|k%Lx_5uqHU^5y=G$tF^nIfSQ6+&^R!wbcGw;>1a*4VsrCrRx(N~3 z7OVmOG#;$p*ibn1fHkD7Br<#mP=O{p3<8Mt&_ie0pR$;JVNme1lCD_8@qT!g^hlT`HJX|a;{ z!+rg{L+59Nt1Xd02u1bwH{pSY15I&dcBs} zWXeSnz(1Qz69;X8KJ}eAD7v{w~fKTaRfI8~**(uGWbfJ8Uh`|P8Feuj3=mS8KQ55Ij zRa#H(_b$vU^LaF5Bz)HVImN%*jk4Vt#eg=xiM`-nQn)73Xog2OLN6QV%6H3sL?=-Z z8YPtJIFbEuLx2mNv*#^hP(t-D2x0sC;(Uj?QNRmjTLI|4P^(d)4Eef*I7}@Cq88-KgfUe+cz1msB?h1kCp(9!VLz2x`_6=Cblk@he?8fHo zbv>0fchURKKIq1nr~W-v2-Q3HW4u8%M+Wt|NU9=|&9;$${rV5`?=N1Wf393!J(A0- zCo-N+!keXJoJD3hrc;VibL<-j|I?&zPzUCGJ1?V}L!IRz=Te-Nn zB$zvJAa4lo91BueZum3vu_F8%yge}9Dg7EpE!pXOb|&-LjD5~2*P5o1L?u0R=)yao zd&nICH#-~cL+%JkvvwD%cNz*ta}b}y?!R~zvING9>eVByfDouI*dRPvxs?HO=!v#O zE;9h=#bUgum9yvy^U=`4Z*%vd5}D=p!?vjwcHe_OJV{ltgC~m|Jq?c7K?KcY5IWv7 z<^9}#t>ajQfgH^JKDv?8lzW{CAE$qZV~s``0i51=Kv2VX4(R@OH>%ty!W_mmbj@4q zaxZ(!m_iDiZvhj}hkNM`hPy@q6=3dTcki4b^2Rw1`)eeN-FN`GDZycX^_sP04K?Wi z;HU-cppHJk(A93MUOVgN_x0#nlu=88?16jj)|Jh@bOnno5TuPM1vduTFPv70D=+d#zCqO?9*h2=*(Dy#?$L4ux z|M&IK@1%6QfPM!QKN3K{4{!|u`j9u;ca9J3p?6=z?ihY(K&O~x-N^d(ni}id^@@yg zctG3rk_{=~L31&!RF1N?I%4L^$BE3QQx*NN?@3NeQhEI7k-T{Gl3)U`!~)DbyhN%7 zHy+Dul*wwflu0_0#rc9^b++XMVQhrFvdAb)7;+B*9l(nm`edr%WcTox@3oLAbJ~ip zchVRBB97CBx&EX^Ntgnrf_c>fy63rJD574feeSg!H|OS!|Q_)gy3<6tgaFX0dn2z#C`zu@Y4l!_Ph<|r)%_Vx0^Ox zA1+=n(r^za(|xEq1aulz;8tWRcmuB$(x&)(QSQZjnru%XWTeAF^1S{EfT{h=9q9d9 z+BUA@29uWrf^)FfVuvsd?-%O$*?$Lm>$T?4QL@?Q@b^SK)-&2?ooiVguZMl%RW*(^ z>0ZMQML9PVqPR5(AuS)rnY>;vh2_0XBD+l?NjjH5-rmap{onq(l-X3St{yYwo*`W{ znX+;SfR2<@y}et9-o2j>`TboDgZu8+-R@)0p$`G_M-Aw`fcFCf`VdHm56G!)j~N8v z4f~-1y>I+OIrJfe;FR_53-zgO(nP`a`t?gP+_#&ROyf+><}+E{+{n#l+e)``fgVqk zwOkZhGk!i(@=&Q|PWYQMqXF3K&9Vgq02+YamBP?obuvz6xm?QS;#?N9DS?R{y`&=e z1JE%>L;%Ja+PB6s$v}=ncpLe2t)2EoA6~4B-@u3v%Qc5{-{wT?T4q^920m)6VZ=bR z1dEVMgTng_L)Mr}f2Q#7XrjiBhSe<`ZUBV8<=f2xyFT=Ou^&WXd~6Qo;%lzZ)>}YLPP4IrhZ!{!0^42`jD<@BL$X2 z#~cFC(RnX|(p+KS&dzJvB@n_b>Vbz!ar-w0-3E^Xy1Mf2sk1#R`yyzr9w0AKCYvIc zEqk%0vRjuD#Ur^XYx#fv^2 zI`*OQe`r$Nj~3960$#fm=tKN{=g{xtnYUJXPq#LIiH`yQ#|-FPhz4@#9~#g>8e6Sy z3L zjl~Ta?zq;LOt;w(^a1$eQNsS~Pd|Gk(@dH1@XWE8>3%4k18}DVbdchvBkjwMzo(HJ z68uyOtQsw-w1mrqYeLW0$A^Cb=y1K@83NFqMGbZ{YOD)<*I}Q#p~U-_CJec{hmOC6 zIclUX6mSj&VEn!U(EWH_KxfLsSh4_gexF9tAT(ip=;Io-;`Z*^`w=G5qE6XUXi%sj zu>XXHiW@Fjs+0%Q>oRBQVznuxsADOTiTsbR|3m)y*I)DR|I=UnwLE(A zM5;KE$$TnJRP!Cn2D)Dj0pj}tR(JjB{yud4Pk{b@Ecc@!_fLTCn%etE5_9r>h1`$L ze;=UtMpA6pr@rfZ`G&R!2@dt=H*c>A9sqQdNnOm(<;|OyQjNw0RrL!m{% zva`BaQ8Wg*aeN2Q9Ure@#)8NaG?N^~e(T#Me|JF7*IW7gXHR7mXDn@-jWvvZHk}c` zfL{P~czf=lBLojXPo!*90uJZ^a{v&9Q361BkYY`<)z(kp!K3aRo@YRef_Oam133gs z42*q$2WWsuVICf%59Vzjl%gS5d?4-W-tK&{XDd-E24u7js)d#zP?qIvEOM2(*zULk~3jESIVvwX~r}8 z^5skUm#@E-yNmTxxl z_T@_{RvQzx5QgDNgi5t1HPqLzfTJ_obTlD=Q^~8+TsTW?td5tVWa~dZznII57ca<| z2e705yvhqT67pQ4rr^F;XixzU-SY3)mZ9`=CB-h6`Ql8TU0%ud z&u0_>*=}}PE0yWI7^0~v& zt6`%I)cXg2=zB-8j{~~D>ppgR@rX27h~57UL8{ql$)pO^C|R;7m2`g&^i3-oGZf;xP#DaM-SFxILqCmzl_;^Z#fk0WUnYTYbpUV_= z;Z?!V_;{rGYIx{jsG6%M+3T89ML%x5BnWF_d*o3aEOFkERGQOAn@R)p@pP=BBM7$^ zF?+BV1wbU1`3!meRCe2(K$=Wudm^0W(i!SUOHCL=1Aq>ewv!HV?GETPmM9jp_Z&k& z_eCy8y`81X2y8*8FwR4y!aF=3h<`RVoQu-E2IvID0IVIvVc4|nbIWD>I{*V91oXaz zmtK6JFy~;7Z3%t`kRh)jJPx8iA)r&^zu52|0{H5-;QlU~Uqkz9(0M}`;5){kX_s2I zwIZeiuyP@cyjK*mH8AJ+%pO*P2K^lYf_@hXaExRz+Lwp z-Y^$U^STyiV;RLt%%b6tjwlc7b?a%AlQ1`(O;}tH$&M#esgc8ED^|_bLvan{r|B5pcO?0)(7gHdtj!^F zfwz3So~)K^W~4Rq&~+@@PL-f0TGHoveWnSlSq;5Ht}7pq*bx2=KkhKMecenH zh7lRm+grmGoDb)9K<|RN1Fi$Qzi%P=4*Nhe-9LSvhqL}ePcQTuQ5xvy3jg(EB2t8O zf<{$pRwBSd*JmX=0QAuFZw-VafUc2)hJYSM5!}-!=$0i7H~b8VSlo9ugWHIU*E`^&03oIOcskPxma8ZIt3yX5RXTLq_{p0I=l}*b`O2XgMMg^ zzH4+29sgat?RVMd*gJH`L+=9mLjn9_0Q7Ds@7S0=dFc9Bg!3>Ia^G#2QiA3F>Xqcn zwaH(q_W*FI8Yqor0wqx_qWBr!Hom{Ty^(XYE)Aqb;kDuX?8XM^)23|0^Siax)EWz% zs&19$-|4Lxa~`>PvdxjRpHBpA_y(dXRVlM^#+r0=g2RG4Ni?J!0x8IM&IpfU7ambi z-?#2mPppJidtDLKRU17~k2#JcuMpNfBd4IQArOP|F@Q@WHB`P}@Sw#j;MoXWj2Z-W z-{a|?^oDps7tkSHiq3E~dS;iU=KWcluep0Dn)wHSuE5@(Hw+1GZMQekGy=gAY<>We z)pP^Ub1B;PvAm9e#ZT3?)EmKCm_Il*Jbw4k55nX)S&{6@aeH z_=?pHWu*j754raNm;<^RJQ}j+xf)gE!v}zlPt%d@misXf z`2^^vbL>BAK)*}Brzj;uH#xS?tO@MMp|{VwdBfglC4AQVz?|1R0O&=n zq%_W3+a@)5W-^HT1kzJMr#3dAf#OYQ1oZse_l`Q?LPgM@%PyevzEMwK8S{89LqNyR z2)Q%*&@m$X_{dcQh~4AHJ=hE190Ix@#{u5G_*MoM_ub~AgzB6Dx`yBp&9NpyK@NQb zeRn)_&~`UQe-Siqd4Ai-|MA-p+cSr3#E7f-#hCpz44=vRpU78tpIJP`bo& z_2^294eD?&cx-6C1I(%8o+MKN8GIIT_O+ z;JmOS++jC5lEcM8z08(o^I;Q??DJ#+%D#nW-fzJ;<6)S)NtIeMf32xe9i#*_%u zR>JZ%s|R;*1E3yg)41fXb#RNBf;jF4g<#t?C;=8|+!K}s(wK4Wbfg6)6V|1x-0WRI z_pWJO;PLZ1Db77~C&eki!#F!^-HQF3G>P$IcJRy;tcoyU8TP1GKxc^>J#+}+7%w0I z^lhWwdI;*=7Jsj6x!$Gn&;R~w*-gfB`Pt88F+G>bXsTg-7?1-w&_uYGSC*=OW{?qAx=-nIn3DEEM9}efJJ3m7afT8*Pp;_+h)wQf| zZ^?28qgbU=RX~JH^fK2jYK6*w!YlUjFqEy0&`;dDi4nxDzBmKuC$Ydo$FU#>%eq>G z=K+ZD>Je(rwT&v}MRz&Doyu=f#GkLP-^jDaPbk(|Z8!ALL5f5DJiag1*8~LQ%n5o_ z=h{aIs>Xy#yw5fS!x-k(ZSqm7#4(V+5Jrdk8i-uhlp{_uMg!orlUtB)Wipw`cr=ym zW-ZlJ_04g;t|j3L{<>W=J*bC;IJ9!85^*pIf{Gee3mG`|j;cn0K14)rf$NX!UT|1$8zOGoc#_VAs==xBZU+dMPMv)NnsI8Ng@l$*%LftEcjR{qn!bdOVd!U;N?#&;cc< zjHN!XxDS8~9W$KA9~#iRN}An!JfuW7bge@XfFWb3@A&Vs&oKkxCkf~wD0V&dPagVR z+xj6M`fB->if{mQ$u*44y63<{$IrP*m`X19@ic`MHzUs2o!UNb$r zYTbtTxhMyK4v%?P!b9JOtq~c8w}nrZj-(i8GKv#Hpj*T4SlHR!Qx|$FDS|+j($LAb zYnji_Wip=0YI)lNI<5!#e0qMl60JxKM89rt^b(X=yb0GiQ+zoYCbB(!ybU3m`}d(Hirqet$zu% zU3`D9>30xDjy&|x>6scK4gb;rF+j(&phUQ$1$38@Z6gXndcXlaBt#gRtUXXAyOxrg49O1S&BpB65;55V^w)BpAf(0_y;`j8iS$^!2T{dEE5)bURN@_o)b zH1^Pg?i=ed&%(DIvJjytc50lb`kiCHArF5jrNPCw!*d9K&rw#^Xh<3Vj}UTA6WKMD zY^q#tUVY024c*Vspha`Y8NF8gyIZd5Wip=**6(g3=T}z*;r04fn(bCD&(GUM84P$F z52b1d!=u~`V_a>u)CfSoS}x^hkDsYX2uNWgt>w;ACDQ@eQ94H%SxCF4nM}tib-~Aw ze2s7&0Jc~bla%0}1E8#i_y9cWeU8>Ox|?QSw~qP8Iejq?7chb{lvWvmQ1YDvjsj9G z(e$hZ+!3_OjZKa}(gQ}ZQY12-%n4M>)rzFT#Uzu>dM%Z45d1zWQBMsH%z2duq&^F^ z696r@zH8LD;`v~>xTd?ULusk4U43Eq^LP}aioh{Y)_rUp(V*|2=P1+L$$WmIdSxIC?akvnF99Gm}} ztd^*%^MzBjo`wsB7lF5sBdaHvo4acTblK zD$Zq#s+X1d^8i2y-*124e6EUSZJVm_4H@7O0MPru$9#5tzff3)B)TYJbj6J#7;@wj zq$&T7@{NtDM056g4`3eSoeZcW)G<-aW=~9W?~>uih-> z{OU9L`Ln+uVR91{l7Ike1kPitL>~y80^x@M*pP96?}q>#2JWd(UpKPwyq^HQQqQWWB1Uz!Z&^3e#+pg5wb-d5Ug$U=CPO~-Ur3D^7V6ixR8FuVodNdVi&*# z-O#A$#u{`5IaP+!+VMF%qNzvX@}yY2Kukl(d;*3#yHabI7sp&LSMv1Y%Idd~pVkH? z4(Q4&P!An{gQ(3E9oI&wOp{C|^yc-vQLdynk1ROgVr&Gb6M&9w@qBp7AOt%H^rkNC zd#%Iw#irf%Y$lP3*^t?8gs9d7jsZx}g-573B3RES(6CP>-#~U$0gm2c(D=l2-ykI_ zpzqb;;2FEYg7Nd`fGBrR*46>^7U=C5RfI7pn75$K+&+%m$Zn@)ZG>YOgXptvd1jCt z&(AMqvvv7YHU8Y#U=2APVDGMmcD7bBhH@^1tgSgqcy1a+9&RoS#0l6YW83l29n5)* zX5Z=;b6CNH4m@5WI;TuzHZ=Wd=EgUQZ5K^P>F-+5WC3fH3QH=y5w^c z?;8Z|EXS@)dEqsKz^?n&vPl#9zWMh1)A!x^E|xlt z1#E6~o}yO+5?E0)7k<5aB`6(w`}Qq?8zF69>`?DL&Jz9|TL-=DA{LDf77XrUe+%$_NyD+88^Q1)jYFaZ8X2dZPC|Ybl6*7WRV? zidfu_#E2`@ug)-7qj7K)Y2nUTk zLAz9d8SZn&W;UE7Yh;3QK)+u!z>EmidfOI#(dH~B5@d3%yqAH}9Gi}}`+>7} zcz6yPMDWgWp3=61({7-Su(}%;tvE~t=~oS@18)xi-LwN*X1kN-xV@{y?OV0(vXT7y z`3w2o>l+!*ujGqoe=b=zmUXq0Xq-u6#^O&M(Ea+lfcj9TuL+O9Lmp@9edCjwt5y{t&!yIFO-JDD>GgWW#q;XoN*-NZ z3542SU%wTQpEkvg4PEd-=$*nOrMAE1f*%XLau^jjJ_KhZM?db7EG8p4n@(hwYEzcj znAiz~Q7pvkkpcpVg|Ev>bGn+(z6P8}Gz^5+2!H|QQGo!^-SBGfEkefNK?HzKu(zlJ zz`(~wPu*o(ArNCm3fizbpd;iCz5tB3E}+u@FlIc2iSRz~8b%ZO?aSBl+qbupOcwIl zvp{5F=GOMFOi`M_5DNPp?l=eyE*PpfPOgJKUoj` zK8D0k8PM;0{oOgZmW{Hl<3t(UMjRr!2OidPBiGm0a`XC)hSM|cuElWrd`?C&K%s$R z96E}zJt|6u5{A?h=38r$-LQzEfysO}muF9(a{uD`M!tFRt>jTHtM!^*J3V56rzk$g?sg^RXeN&zeIcW4 zB1NTu{;_-LLxBE6=g>cS=pUJf?qRraL4Am){bTpg-#3T8$<{JYN3xJirj>e+c*!2X2TzdQ0O%+qL%0_|XH`j$eFB#IWJExp zKybrCnWOYjCCnFh_q6NAcmZIt+xb9>3q1ipKNeZv&w(VyH3nf|Z0jCBjfP}j$BepY ze_mZ*fTX|48FR1-Y5=i9ntUg-$w+phz27}lt@`&0E(pJGWZzztMuLg@a16-Fqn|t9 zSp)k6X;!#U`}V1!Jg(1EQzOp}Q6Ol@djtbuShBhS_t3kr5fm+Yqv7{h)>~~Z;~pvX z;lXYPAr4A@NyG{Sd=N?o(Tqldq>_v>iJFq!4JTfDw8A4S7$=X-nsKYSHxHfjnQ3I9 z1@HjO{eCiqVMeOYv#%!@8vwoB6>aT3OBM~#LE><4A9$~Z3zXqBA%7Y< zdodXRx_j{G14G%@;CU*WMEE?(bK)#{1uf zBBVnRhKJUvKP0+Aqcbp`!|}HcLl7bE9-C3A;C<~o_nm&|KXy{wCqTa|bn_5{<|^CC zMLd!x%}C~D#AXk>q?VoRU~h2u4Q~Slk3$|&K7fJM8kL(j|IKZ9nipt zhLNDgf#&JY66DL#Ydn@2NP6Q5yRLzp%rJMPy7OJni=He}4UwwfaeT44^MUr6&!u~D z4%QAN$!vB2=(~#Kb&|3pyJPUH<9%|pWWOZHzkI_@WyN7P@Hsqt6ilo$XB#0h)~I zrK`cP2XwO5!EQ@3jZCqTk3|Fw(0R__=e)GCIjf++To+X&-xj5Ox!K7!8Oz1_QyHU; za9v1+)Y3;ziuwCa|oD}5zD2T9JSmd`F*;P z-`}j|H?MBx%iE2tcL=doGJ`5tRLKT;?7ES&Y$RvnOwMOh$yZC++}y}#Po7C$@3@$6 z)*CrLU$C#a65A3sZvj9<-m?{zIX`Du)n#NSi@9w6fA-$2N7D4X5s zCYwDJHPk{%8j6xIW6Q?aFlK;5wV;OPOi@SSz6*5FP@ zv$Rj`Nm-b@12WTD^(EkNL1%zrLB@i3=xH`>0|?ts=I0BDF@rQ2q8fad*P4=jv!i>@ z+)e`lD%NR0QimMDA|R?*kFcyOT8jFJ!U%1z3VtMn5g<7cz)ZU`CFZcxb7Fy#KX+RS z_Bw2N20Jt0@}_1jKcrQo-k&NRTbmxRaoDq9X~~JaCwSiYS)5Jhc}wFM*(MWzd+rkf zFB~Kkz87*^WrSKRNm115GW8d*51TF9Hb=b!j+dGA<+sWPN4CUm?+e?q*eus_UCHKW zRe|>_FM*x-;FJO1%ie!$?pruIxgjHZPJoI=DsqxMRICI@g^8j@dT)wQ5X<+*AcjQ~ z-LDRnlVH|%_$h6LV|t<=X@KatsGSzU4maXepm%kB+LyKNzJA|p_dTzq&CBa^bq;+G zN&VWT^}0;kv_!;||+c~^tPtNYIBqSxgZ?BdyV8NS@RzX*VSQ~&oC z&|kirJ}sb=xy}Wah7L_z!FOsLhdz$#7WcgX)3IumbDo^zUP9Pv*uVCqe0$NAST!vk zZwmZmzQ9Lk3tVj0vZ!z|j(eTy4SgX;40tXDw)m#Herl&yOc$n0pOTR^u}2-`;B&#T~x)@b3&`Oz7Baci?cW#Zjk9)WEe z*mAublLT7WX7W4+Y3;D2O+cqbE!pV2WTqm(&vVL4^BB9x?Ve8px&^vd0s59ew^PZn z$GTZ>Bnz*~#t`=?b9^b5Q#VT5Bfwf+cj?=^4)P+GQ8fZLAI!!{b|av3`_x^q0R@k3 zOQbVwckXY|hq!23e6U&zppQq#T1jAQ!tFjmirWWv*Ma^`V73pi_dWl41NuIo-j|{8 zd;cw<8>K3VCM4JRbh0MkK)K4i&M z3?$)pBxrd^ToTJdkyjz$G@g%TSL5+|g&&-s;|FI8JXsZ3RSn+mH7lfmNAI+Vhp~{E ziXxLza@;91o{Km$FfITTo;jRMv0N-AOSe6waiOjN03ZNKL_t(lnQKo~NsfP$fMLjz zX@ickvq6CAAeBBona3=#P7hKfejwv&f#|JwLd4V06pEMAoO z7?3baH5DLPIC(K7v!_j~1|T-0w0&TLoCYl#C0c^9W@L_lz8!TlK^|YTX*|i$uL8Qw(66%Gf6)Ma zUk1956n7n@6X|t7dHi_0pjkqgB~4k887~Sj zN)qux@2VPuG!~{fiE#%96NF(eq_~Kgy9mh95v>;%ypGt>g-d~87tn3i8K$8U)tpNo zY*8o^(ASKRWTs0+J`D;O2(qtCK;O;4ZApF0qOY`?VgD~#H+!;%ghimRAY}s!g1LY! zGjM{01TRw4HUQ2n-DG)XVdnqYgQw~nRq_#oQKtgz+>6nfXYrue>bqO zpl$(qcM-JD@oy?TqvkJiojKxV0A2RkknU_x+g=OHSZ9@nl?~3^bAK5Wu^M7a{d~Qg zGq&>0TsiAVd<}IH`W>x#yN|mII*s$*2^V8H*Ym)#8AX_Lv0cUgxA2LpCgP=C!sb?8TM{r<^5S@U*8XzcWGXmD!*!W}a}VMgEhM>qeq;w=8Y5aRwAk zxw<69QFzB>pX%S;ZN+3PsLN=Z%zbNsQCKi1Xwt|=2!V!F*R?3J-1Nn{LmD`cYd~PH z>x$knl1YX^A|+lC0dib(egfpe4maj5I|_4><(uGR7X+@B-#hkab{+1h*D|(0tfzfrnCaI5`tJT#JL6`%z;1W>YQS<8 z{0W@P)e3D*PXQVeu@#`ltoyIVEOJk9KiP^hfX)oPuC%`{<}JKFB#d@c*ej)ybzO#T zJ>2;j^Sl#4C(C^o&_zeyX+JTxb_?h)o6+pkYQNg!z78*L`rB>E{hE^dtH7Ek@@Ea` zS3m1lJwqRedT4>8!wB~i;9lTkNb?nDYr_sp@U0zVw3q8`UD&%t;kKUu0BjR#1hUV7>Y%k!d`u7FN3=Vw_rFC8J%(z0(x z%NRWLzR8kyz}#l&7SPEj5V0N67&p?S99yD0naQ#wOSOLMrhhHlZ?bKl)H2_>=-SM% zWxBTW-m8FF89-++!BIVC?}p=ehX$@dU>)`*{^|E;O4Kqi}>EOEm>L�(#^(l96(jK6C-!^jQghmV9NiDGTV# z(Cw&N>)KHvz5jTv~mR)m97a_kVZ)1oSvf1<-}rpTt`NCE4#J z#mTJx$k%zlS6C6(`NW%yLmoN&& zKr>q=4N`{Y%(>g*B3s~magM0CgBPb~s9a!PWq2|_L+$oLq?0*WhwStbE@l_95Kkr( zQJ!ndTD{FpxqUmPMoUnm=0<=a*i0uQ*(b@$gdkVTK21jhqys9Eg%|}fBF}**Gtw+g zle4CTJziS@@EuZ|1@w-c1(Ti2Js{?9401elZjYj>q~uN@v4AcLVa&`(C^O#hHsiEe zxCKM9+<9y~Cfg(5z1J+D?}E~9#_3w44v~-5)&cd&>Y|c!QwJIh@LZAUFXxjQ@FqCQ znnKQbk_@rQa|x`dnI5N!WWb>p3Aosbh#20OQ8W2|uwr8Zj;q}66tUtfL=8% z(%}$A-AFJc`U3{UEuhOj?_}ugp%c(Q+GJanyHs}!pocq}2@;TAInL_>nO6lj*8%FM zdF^%Y|GWXcvCcuSh!*-iTKM~dj9v@@l|Cw;G}tflkJZVkL`Th*Krq1he2Ev!1(tP%c~xRoeFT`Xr z#cDR!F|{zndbyIr<+(i=52ZpN#4={N%)D7q2xCm9BMiwNCn+wZ4mdMr>#g1DQrD@u zi>Q(r@Y|iO=)F+MO;`H%{5&4>+N}^$@4M;YnX)UhJ}%r01bR=Mh0NEA45+mty(|rDh8+s&%HA{V-LizM{dWyKHk8sG4l$k# z<^PA{3C=H0QI+~Wj{VuH00EWPLhgH0F>o8>N=N^AGb*>uq~Rc}8uY9R1TK0J{9(}4 z!>cFA$sBx!4-e%Ezawlywl5A!}k7o`XSUmg2o?TSF9!`FGd3h4J`u%8vs)#`Zv z<8=ZNyOrJ7zK(S3)iw83?U(EJ@;bo&H0NX=i{4I$*lq4siX=F{GDv^*v#;*oYs{hF z0{Tq>&F2m1ERQ!FjiF|C;K6CQ*tc-#a^?8=wZ6f(zx6i8m|^kwIfCX69B+z@taU69 zIzw?sBhjp`OUZ0IV+l&K+)?03X`7%ypr@#el*p?JMX^EE2hw9ar-4gVb zRcJgQ5|Wn>3T2gr0+EhMG0AFBcaCI`#ac~Lq?EbdC^5|QFdjtOH||MJ>jd06ik1YC z?AORBsa*wh=CKky(v#e{t$Csw!;JRQAgFT#>G50Uxg|c?p6;U01$g_`5kP0AMli@q z^-(9F6No}Og%Q-5$y1Nr^iv!5^r>%OHOSU$DHHQ}1XRlkelmEeziYw3X7juj3TB3J zT^T?(qfOx;l7NIQh>O{oTqjNtL{T6>$z+e`pZjVx00clN$IH>aAllBXTR@i&G`;Jf zb3yT>E^q}%r4rF}@R|;+9(2*=%saP9Q6d3jL;mCYIA&O^)^eW2wG6;=xkQvE+c7?V zk9h954F*e;?&W#QOST0rZD$GS5}@$hv-eDpZQCuN^F1U3$|1Ne@=V2xxXp5tiP#SR zZpnB}Xsl*Mhg}0IPI`zz3JG~6^+_8>WpAlvV*!C+!hS!e9c%zfK)28Lor9uLzjk?E z09^%(tN{xFU0MTOBi|97P1j>0!En_zIImpH5CPHP7SOL$A#MTv<%IerK))`#6~FAA z$FEw3ew~}y?lJDmxIb?|w+tPJ7MC)LWM`EX9RFw><2&E_3bNS;*gRk2VDu$4{SfP} zK;CXpm#QC5FlRPM(56@lOWV?Oja&?)2;<2Z17Wf|lBr7>xv7vBJy!V!^Q^#vV7^)7 zbh*Z=DnyeyoeWWy70O)unHIEVq3mmvts{al1Uvy?s%;gj^Gz4EB+ybVftjOfk&M{& zGNv{h3@|i+9)vosrP(NF(KWR7DL-r6)GVNLj@y=x8))`!ORfAY{%*;18@EFuCL)|Q z>Zq(PLLn7>#0m6Xfh0;W2%@dm`7R(XmJ7)Wi3u!sOF7&cf|M29Q~})rknR84|C6OH z`rhmrTL-cBG7F3cp~&(M(?rGv30@cHr(5vu8=V%g0Rl;MT9RhZJc2V+bvvC3(9uI% zRnvQ)^Z9DAYxyqX1jn9yE!}NZ*`tgu_s=lErJT+xMXQ#$ZBYtf^TE&A6uGd!8A#d+ zf&_|%_Vf9EGW``W3Emn=^7p{ikv_>_detl-H(4Bb7E_Fzprt=*sOV4G)s`w$_eS7er=H>h*qU%en=Ai4I(;pa{UTnnTAorxyn| z71h%WUBFx+jxM4qo6_-=HoU)zXkMH0Q#$dizUG?5}@w` z@axJqH=m!EYbHPIk~vP_EMrD>jV5LpU6twj zT6@?{qxP156rid%l7Ujmj^(p0A&c1@s~t5nuSU0{>auj8Po zE`eOm2SsN@97Z$2FbpuCp9|qo1Wp(zH7&-Y5h&C`!d z_bnmL=*^Gr-jkVX{7U!She*2aFwh0S*lRcadN~h9(U1F86glEJ5s@Nm1Y_@|hS~}YNQ}Ch1Qa{h zyY@85+Wqsdbjke> ze(zhKXoBy8&KC*Lud7h(1NhH7L+=p6cS^g3+tG zc4YC%s~XFq#QAE2v-Mj3&xPw*wMJ9x;^uj=Ecja9=6raI&Xi^&W?fs$Q7wz|wV_){ zZ<lTu5a&vDmzvSLVpjWyWcwRedc#^R=CGX|HKB;B9uv z8TOdjXQ-v(n#8t1`lwvw{V0Lwl#+cjAYmU}%D^le8=Y>abCgBS5hp-EH_KHnHH{)< zJF0b7vCS?x+>g3(#f?nCn)|QEU;_tA?ee*U!$U+KgBtxjjtFixD^dItfgb{ynKIz} z35x73cdZ$#YfScQEJ}rN*3_81`A`8*qeedaa&-a%q0wnhyGu67@@(~z7a{GE5DyqZRaSDP!&SNA= zjTH*pwopRkr4bH6(`NY`T@(UZsKFnDk=>FzOXm_qbcJTuM&ei+20Oj+LZoM{;~Mw< z(t4LSNnytJsLIEHfI)yroA)kSsu+rodW*JVmQEd>7A3`Nn6;C9S$BAmcR1@qc!P-$ zKv^9jp!Z&K3+UHsjb6g{7aq{B0@xP?(Dwniy+wY}GW6Ps;kRoHB4AavD1#9a&&Ay) z!?)kNhyUo^`#3v4M-+?^#RIIC1sX2Kjw5}{iX=Bjg)aI|mDrf|5tt-#3D|E`5*Gn0 z34Fu^2oi|88hxkz;-c%2RSg!K4d$CnY%`m#$KTISWbBJDvLNwZ~7z~-kHN=#KU{1~ggM}z0tGq&2T-s|AxQe( z;yJb8&TTV8PgtoTk{C5R89|jImU61 z71^=j0b<9)JMISm>YMN5{t#Gk=6rk~*``8XvaB9pIbWe^TFlln`LZ`Pov&Q!XKM!3 zA&O$LQk5*HYEWjmj44q&oqbGF@pymqt}hy1Roi1-6j)?Amg@{fRpQ5s1zd-USjfzztn}<7s8t>BTDQ6J6(k; zqas)(SvtW?W~ zGG$;)c>GYUX_Lh88#MS>ZPpl%$7tF{vP`ngrSf6Q{v5H(mMZ~tRaEPxuN)@{vLeSY zG1jUKAX&XJeRS?4x5Il>dgaFOM)Uw!GB+7~I!L7CP9SFwoxA{67A(u%4>>O5Mo2KE>kjV|R)0kMzUs8v)pscR7A09IWrrv08W&xNV05qrbV}MHNN)lCHbZ|2 zzMPu?UCN_7%5FB(+1&yc$(tUw-1+i*UTtdkx|y=w-e(|f%#%BjCRj$@%W>sIG!HibTva&;=URM}S$HD-2 zBv8@Jn^`|I`(mSpFZ`S=FJuL>WptS$Fa|fwyg6n`03QxVCR2ZzuH^oQ|KxXW z^h4h#ydvb7D`GUe|Npde-d8V-RV#Z{K(PB+pC+@muf4A1^l7$pHK4e<|JSkTcVBbe z`}YMkyU(-N7RxA64=;(O-#T(@{HOouZT#Vv-$L1JI5~{aPvNo9CL_`!0KMfV(5BSL&l>AhaiZh3tVz(*{k7NTY64PM8#yy}o7Oo^ zK96;g;*!8dW`|BB@H%V1yoKtulXoF33+~$v(Ks(QN)DA7_f}@n%eoZ}gR1MXu3bFe zY|xJnQT9I4WUOROO5XAwHA;9l0ov|!S4;1owp4%h^{=zNSC#v3+OOByuEb1x1cP2@ z4*aHbuy5ZPu-TlJuYE~Zg!jUZG_?Jk-ECTu4M$P85;}qZspS zjSrtbM(+pMlnt`7#(cey-g-KkV71OP2yFQt&5kKqBI8QvkZ@cr*79@M*8)f+@YNv0IOY*Z`Pt0ANq{rV@~eRU3BVFpH2tf9ID6jK z@>ELkhJi0?c$a`q9w_&tqT8ChPYH8!-&5?tY}5j}IIwjMs-{Q5>m;Pa23hOl@nQw{ z@EDB~A`DWUj}IJltU@s|y5X@8kZu9}<}y-^ASe_d9Ey4Y!+**RvQ!> zF8(FXW~Tz8VeDecx$fyu1V6$!l`NHuD;M~#s6-fri}PYrVwsncWu>7f_M$?p0x+6R zvCKC3$&(M^1u^R0!_yZpP&5^?nxkH^Wa!MGo2o~gD$AS=MrP*}abb2IM+(rX*NcyO z8ii`ELOpL`y!%r6ZyUOeh1;<;?W1cZ#C-}P6}AzlG68(Lkg3>*$ee}@NXYSPQ3?5~ zM#Dy@>BZM%!u85x);_8((8|JR_NAq4TWVDTmomQj`A5h1@%;I7oS&XyxmXAr{ZN9M zwTzZMe0X2M!jQadiO>?kj_(}H=h8c#Qmup07^kPF*c1icedk^2zl+=`gP%|t@7%Tq zEghbpo^Pus+;;|Zr)OtqNx*6vY|QweC89AfW4l3S)Y*bq&Ctu(9n0ty-n{=nswIa< zwDKHDdxpTvvAxkK#gIyLR32;!Ip0aB{`Rc8SeCmVM-qg%ESK~CVlSWC?VRl=v%jtd z(D{25dy<{^2GFu8E^XJkxZk05}z#$CP zzLmxqoGs^hY-?%zE6@w!+sesuVb{f2vUHYH+d{{*@=~&70w&uUyst%zzG{WA#U3)B zJ2*HHz5x5mckbRn(^6Yqs|1$mZiQfkXRusjI-Ouss9!jF4b%iD=y6+Q-E&%jfMpf$ zR1l>WU}u;WMTusM-90f|za?H)xlnSBD*st1v%U&C~b}a>v3TYiNKw(nMaXgmVIV#5E zAh_C$+Y;X_cnbhC8{YwRTXL6kyajZ1N)wFkNe-n(gU;yl7zO;Ttn3cMov-ILrTveU zekGun)GDYsr{5xTV*L2U3ydE=f)gfaO5I*O2(TzONT?up3+T6iZqC4`%FwSXk6XZf zRat#E!@uq|`%3Qnw!eENZ`#)D?4RA%r`gWu-9xA8X-)zS8YE7DNdx@$oA>a~e)ApN ziED5yi$LEtWcXI7@(x8_2)L{k7uYl_0Z_`klJt}e2S`R^498OhNs89hk|}++g_Rye zNCy+RUL;~N|L_0xzv1BESlHbJsVGem#W7BoGa(Zdt%JY(>%SIFaRNGBzgYGqc#~+B zM6R-p`yOeiy>kH*ik$=jjz_Wf#|g%qWhaS?Sz$oHp>d27_^gJz5ZX-nU7}x(NRdQm zgj#~|GTRPAs_Uu38At5c=VS-HZ(XqP&iAyUB&KCvedtdM=ue+~U@~^ikTrw!b<8V_ zu*pgRmO+xrIhSn;L2!eA{EdH%Ak=JMf?t!xNq}L5ZCI|CQ81A)pey zBwkI=n18cEFVssX>5#8?;7V_ruVt^AK>+{%;o}#=0?)Es2y_H>K4{>=K%;E5Bu?WS z>Jl($Sj{g)nT~z^`^UQdB+?0lyGO@JV(P~`LZs_Fs_a4bsVNJ<^Tn*B?s&)cSe>3I zUxME8jhQ{CHhic~e0jAJt6XO21av#vrxK~0-_}gtf--;K73g8`<{B}cmgRSXIcM%g zh?T-ZmnC$2{_VEp{-HwO&Mdpl!UfPdZ9p(K)tHXslrk}*@~#5##*Izf`ON&fFx?GX zp5F)Qu`@$&sjSyXxxK8Iq1TwV0e*6FipkrL;6)>JGAU9cP9v<#3?XzZ^Hq<1CF2|4 z{2D##eHo?(IWH5ZU#E=xI@`T&+gFe07d=DYXYO*H65h|G(gB5wTZd_i>1z@Uvjlpn;;V40x4lo#u zkWQvZCWq1w&w7q#F>CXrTsdE?u$nJ%akj$g*#*k%BaFufV!S~>XCE;g4UscTX?x7_ z3V-!Ce;L*Rm)-BM7yBZHY6-M@J(1!fJ;|&U)=j(yJVolOD0@jgL~c zN_5){PFCw&o@da+KxmL8Ta9%g)-{b}yyPXYtX&qWi|@FBTyO3Z{m=>a1a(e6$o)W; zdRCzolE?;r1;iBNFq5a9xrZLpkTEp? z+q1pHz`=|fn&<8Q(%^-GFWY}?8KhL&%1~IMF;eh<|uA~BIuE}9^R;3{3l=iGXCJV-bP(K7sfO* z;lz=;p1|o`Ook(6ds99(iDePxLiKdD#^3$$hXUy5%QYxv$?T-&0__qAlvKnl zdNQE1nwD#s-Hy`%60ehStR$iW9$n2ijs^h`VPo6gxM2NE&NdI9d%5o&fdWskUeQwApH~J!I+g z_u3L*Ye51Fqg~JIFO?Ba8muxbvb8wjF*9T(XG7M0+hEhSxHvtNfQw^k_m7XI70r8M z$m^5nghLz#7={Uk170TvTcPyYhhw%KDhWIonE4T1?*b_)lcT{_1gi$xcJQ~=hQN=- zWTkUz5rz>`9NPzMpLnh+%ZZDf=~0_3Sz0beyIujB5`Nk;k*ryI=ybN}q!q9W=(frs z8M6rxETG#~fCY5v`LjyUnejG$ju^1GQhw(>E_{Git0xp9vVjB3>PiA+z^JN>1auPC zEugcH&cOGBCH)Z!jNg1H)wY!8Kve}g<1}6mztMKmZH9jR8Mp=XpEIDpD${?}4Y`jL z_eBTvsBy9MN)!<=Y<;}dxcJY$_CEgTx8K2f^O2076?uiOCO|mS-<_W^JD7s$ zj}8xImN!U;hzAoOh|oG75~sn%#iZ8(HS<+8fLAWFm%)Ng8} z!$`zt2pXX*nL7H#UM&|zVV7I4b0d;s%di}gVkWMnFU@piaW{@~EdvOVa-|tapoSr` z(5sfaj0754S}pNimUq#4sNKp4*C;tk%i5)6$PuTs-%mz%2Vy>9O*h+RdMX+K^RqKd565z?IM#Om!F@b=`V7M~lE0C>$Pq_s z=@Zlm_;>Cype!*;23oo&bKP~Yrr1jq$k-k$2Rs+74sqXw_3x74SHkf-DY>(>&h1)O zI{}>;dMNg@#w^I3KWRyru|;uSGk`9>_Xg0(az{gZO3j>i+Z`_hI^Uud9ciQsKu@)FRv!}4urE4-ohq-< zolf`wRfD3|%#W&n_MWoDI-8{n@RX5MF{qr!zIN|0t7Na7=Yw^1mA=(+X4=HM$jTD) ziv^ae4a&~JM<0EJyT|u%F#4@Hb}O{6(<{HaE1z}$_GRGvI9fk%zjo2?zkx%rk1OzLd+g3H5};pq@^1nC z@+)xN`N{nVX*)+i7JEO!19bS4-+74l-b|6FBP0#bQ*WH3F|!)^vrIDdvuc40%<SlxVD8jplrBY(#g1zFlApg3E1kAME~X#ex~XF)5)oxO|p}s%WvwGRgAEu7C3J zGaMh^!)!K}tTGisoGXqr)DPfx9J=!L4h|+$sY;hcfj8fH1A(g<>cMo1!C)xo&Ccr+ z+)1Y7{^}T@?(6QO;jEk6{tCkT&F95 z&Q{14u%#VjozV<%`!AdKSn#(CaRJqaXU|5rbD7b<3eaiXLqO+wE1UpLrH*M52vsEt z3LMGrEq;8yfk%5`j#vf>qJX2Rtw;|O(D%)ue^$W!MF;eK`?oKaxdrr{Gb9U=VGr+~ zxa)xDbu#qpUb8R4+V{D?>KQr#eOS+BK@>oDJAC(d-o|@xj!>}2Nm5(L%%H~REW_fX zInK^z*kFS?s_|%gELlxD8i|6JXBffEUS-jr&9#Kc43d3n&JH`uRwwZ-o(}Nj@iWXX zG*hk1M!d~s)GP?FSgp{o#9P+*i@*C@Y^qMij@YlCq(iLg0-oa{;mmp9BlXn)h92xB z+OdZ&WoQC=;2}1Bbk*ioo$M&SBnH`Xs|9p%2@AD{EuSv9JhMz{E<$O0Z!5Nnq1GhfhJ0h-5>u-5C(DB0%kW z2aPk=8ETPKwW2NTk?Sa1o^^Qs;sp*kYByhMm4hRNCN;C)e+DpZRf5Jk6p^W`T*m5# z=_MPVLO3=k;`@Xc=jxc6{b$z{3#?3C70}t5QT+hlu*s#=-m0HE|L!?Tq-4cIbn~ex zPj=sSDnUV0S|B3Xs-L}^nQsBzP8^ue5}pP7_9hUr@1a(^1!H}U1$6USy;cgglCiSS z+CvxOqZgs3MXL!UvZ@woVS+k&3?D8k_|p-bWFU%*F{cKaRs^G*$b+kK%PSwZfPVA& zxdrr}1EAkjroILA%M*UxxhT8@gXTilcua8L@9|&%&Lh0@<`7vlz>q{Qp8{(o7B5zK z`tdm~E*9wNQ$2KXG#ttp5t-^7+w#KzlpEzDFJ;Mv3SThoatR7)gob5mieFTvOu>He z!ACehqpKI4*;MF+U@N4vqK2OgaFLhzcYpCcoG&xk)`R=^a4?$S+4-pe#DG0iI=Oie z?RXKnNm7Iz=gfTpb1Atyw%o3O*?2k<#RX9aaYmEf_SQvshiwEyqLSLC$%fc3cUuQ- z=%S(ZDwW76q00=MnQOpaE=%_|v(?cfyDhdKO1GDmfwkKtfs20^;DLkjwq#2?OlFH3 zAn^QhQ6D6eZGXRROIhUE_pRz&eqXN@#K?VMHW^X~hfZG=`|SZbG0)L+eF^GzhTOx^ zf%fjBD3w5hA~~J${?;Ikv*DDlR8SSw9#hVy?mqqE=NC&124gIjMvtD5DUz0r%$4)} z)0m|qAu`m;3M(*d2Mk831O~h=Z0X2r&18XOCqc6^MIprBtP!@QJ8H@xt?tIAe55(Hh?hq#ul*6e7W5x8yId&_B89U zS-q*;&^TrL{+@`-$q7Tg?5G~6{0xq_bwP-t*Xg5Pcj8?5bkiX^m;&ig z?n8102~lu zvnehpB(n`C2kOp6S&wxNdSnq8y*Pvy#;BbRYg3ZVAD`gECr^=Q?5&a*=ONEGXf2C8 zs}T*yILiwBhadg`tAg^DwaAvTTfC+xb{tDao-kwf9gKnyQ_jOv)4Z>xkCK;M#&imp9M?km4DFV8^r+BQaD1ak*9BpDBxHWRap^us>a~=EE zYUE-iU`Z|`iH!dk+}NzLtuGbge52d#l>}U#$qJlum(Qj`SWyZ{b8Jrctrz`rju%#i z?Xh;~yd0jRJ>w)9V3>}z4_nn@BO8u1L)0L{0EOuv^PEhDeCLVs9>rhCN>7qlCI`fE z%qX(ia(Cz2{=f1r*zeCaIpT=sCz*`!)r~r|acZFVb(>9DqbdryJ~EH*DbPiU22qYe}AfZavklFpzA= zQ$rg5PNsWKqF(P|SvQz1);K904DK8OX)2!+b{?Fr5kPm?wz&oLeVBdY^S2rL&p1Q> zG)i#$uH1Ft|EpedC!i@imyhBDa~7Y90TF_X6Q>dUi*WceI3BB0CS-T>K# z<6$M9U%W87-oBK<(T75eW0{;K@Cp}Fpsgf%7Ina_0zMN-qWu z89MMd;>M}^fTm10lj45WGxX2u=Y9+5|A2u0X|i*>_*@13UwuFyBdJb=#oT*CycK%* z?l<4T!{ZbyFU7zKP|VJ-K0C$va)XOX9ntQNW4tj<5j}W_s;-3eL@QCwJJXzHu~;IC z2dIiOZ1P-eMawEjTb5#@dj9MM7H8-9_yw&xmpD4Uhj-umD#9ejVm%i@7P@Uku8(C= z;rkzbjE`QtfEy1aBbm}en}Q*g6CtMfbzBOlX2igA)i-#qkcwFV`-UC3}saAFZ$ zdeo7Eh0OvrE7NlJRX`Ww)Rx%R35Yj+DcL#u`ec;)m1cY(JD%GXKES1-95Yq|2eU;o z=NS;N&0tAR4heAv;JHXIX9V0{Butsv))kfdYHZdGvQ3Gsqlt+srEye?StjjhDX_!8 zWtEn>d5oOvo{WcEFL3VHW~C!vyR+9;xlBs+nKJydT%Gb{TV$dc{rI=;PLL!K2ICZQ z9Kaf5;G(i9vz~OV+lec3d*uHPo+K1p)&});c*M-d+fc%hj#yC zUu$A_3%jrV!m->xjkN2&)BZ)w&|7zmkR^9%0FUr?=;Kem`3MgW6U^NhVFMJ;pJQ=) zf<;kc&7OJ`;=y!)FHHu({RbijGd;R1($)?|L81h+`2uM=1j-Z91g8*5wpycFXV{!w z;QYx`EMA=A3}dYG0(b5`zQ0JN?z8Tym6Ga<;GU0g`XonDb7 zpAEtoDM7{eF-}6<8I3U=4TRawIcjEn9AOKo<<6csg-jhfemMx~xMl#9z-Gl)ETFT4 zYD?})gwyi1^kb#^tr!yyl)&HZI$MPvtV@D`IA7!RtWcnC4Kh9sp;R=l-sSO#NQMjU^q%~bU4L` z#yk-j_%7T)LCklVl_zi=mdb(QU@Ss9O1P_0`jMWCrV#VaC|5?7m9OD-Ne3w!sv;Wl9?ee_WNi=o z64Z6!)z-jOP~U=Vb14{Ps|EI0_>&;4@89YDTO$D8XFGsSjtO6@Z5AcxZK^^!DxCkX z8?4!Ofrm{4Tr8HDJ1Nq`1Au`lO>QV!#0E~+pmAGxdjNgknkhlf&f_X@?dws0-aYi& z4E^PR#re+f|L*oLyQL)?HFMm_%2rCGy7PW!O1tiTuiJOuy@9U2=j#9M9Nw#5x6g0= zx*PhY%zxkhTz%et0rtJ`x(Wi{v(Hcd>i&P?^W6er6QlBDhz!x{x%&b*K{_pzbnMjaqP4S%qSq zpPBCAt#i%8wsmpYNbTXDjx}{l+DI=y~kBeoF zlXZa)o}OZ31XgGaGe~10EwQ|Q5Jfmj2Dm#MASOYr)694}h$JIsz(Q#Be3ouKgaLck zBm!!NZi!Vkld|`6WyZejd9)eW_W7Q3;3kQap0O&8QILn9-?%J=8@+8>!LB!`vVxB3 z5^yv@i^!+YN-qv}>`Aj1DvnvqK6?*m=NIDpetLQ?rFiP(Q*0&R`$j!dpIiYSE++sS zAH5%A)7F?38R{j;aV2IeI<*a?7t2}YI38e0j*rH|s=t5d0QqJmyo31} z13g!OgR|>_8^WsrC#w*&E>7bXr_Y~ZvpU25J5#*-l`mm39-t#wP$%D|xsOV_23{yt z4MG5CsY&iipd*7c++7ZB{5v#!}%+xd`} zTC`Glxj6&BDOj<`u)8*V;`q0fmHm43uiDN{*}cDK_et2?bAexa`n3Vw-bkMZpx*?R zUvxls+*;%xOD{r!5|6wF|MKBOeBmXcQhWfw3?4h-<0R zB*HN`n2hjXI+5d{{O`Ib;4}`}iY)mC9yP{2XY0IH6dUQazwzcBeCe(G(lY7#O2C}v zD|Ek;fQfEr%sxp-V?r+H?b0!BcLa@9hRa~<65Q=IVt62SsihL-sE0s50N!`pZ)W8- zBNl60BgsoJ7vh;wf#Z9vR)Fs*$jddYH{yy{ca3DzHGAHiRA4oP88RK}O?EnhRn9^t#|p9^mva|ZP5yij)c>1qY#D!5+_7G4X`xxCuP zZi$?K{ds5TuVemV7wFxC{WMwlP4C;6d4KL1Iu+BX)9(9N_a*M5!#}@w7r*h=F^VWd zcUEGa=Xkzc!0TMRapxZH-M@qJ(HP<35RN|p`dmm&WGXvd1o94gw?@_FtRJH#Go66G z%CWpyiYW`TLmGL6hetwg8jQ!XSY<^fq9j~E`G`UXr?Ul4*9AU$eva8X7a6sM+~ogyT^v&R(?A5c3ruQUWHZT0mF%PhC)>WN>YUXs?^hm+$DC?_Mtr2$b|B zOldJ^F+gB$c`Xfx>i9;m=c3v{Kyb6%U_k<4#TjgRt`a2J3#~*8UPhH#^#MYkBHf(P*CBHbI*=1{dD%yKU#c*qN=gk(2u@B6d#~(L%ebS9X$T{ z6yxAAW*0NO^XN->_T*zsM?(z40OQF>fc?#Jj!`;B8V-;~DTc`qb?accStBnS_{&_z zq&h#re6hi^)8{xG#rVpj`xuTm!srS)k^eONb%f|f2~?gh7#8?$g~Uz;2*}#^Y)8{B z0iM^-chua3Ee)2W8648TUdV5}pR&!iB+hHWAd2(rcA+DnTM#9nt9c9g2>SQ3&5W&a{G90B1*_;5q*dE3CG?^|pbsCXgPn-X2^qjP;cU9NFamx%8^*dCuUNA$tK z@D|WNdxrjn19UM6+$js}YO8-9fPNKVzvvlyM*){iN3UjXgM+rkKb;=ow;xW>rv;o@ zgISj0WWAE|;g=sg#Qg_%kuW=-#ArK;Z)9l7jf_k6tuNM`oyQsD5`9Uxs|FPbTr}}G zUtl?3A!on1a}XTRb!&q0Xe61|#d0BF!BICZ=wamHDq{m^;MW~BTj#b(WMxWbrNQ&~sAcWas6A~Jy0$AD|riZwg z%>=NR;j{coz+lGA&;99(8D>R+H50Rg38L`<{3t~lkmaA^&wlt6S>_5wfEZ&n{0)L4?K**7$YaZ zaWuk%<74qMue%Zr8h95QtZSg?VpM%7fl9WSV;r|Qnk2aMU@VMvYOzyie+!;umlI68 zOW_s)J1LVh7|~HbGWGemtfIVJawji>=R3=^Qlj4IdXD%ICc6;PNIa~CP-#V3_;&_L zcKeikwSaD~KU+HtvZO^oxm9YW*S%!sd7c4oh`QGjxb(NFEl@CM(Es!MtrPHXd6IT^R~61piNU5qvt@8B2)dbqD_3B1~F^494OJT!FQ0d&2Wm2~&2$JGq(>g)DB|EpedzXkN2Z2cb^(67suZI5POCcS&%K27$% zZ@Zs&hEBifILkqWmy5_nRP^{xI>PU~IYct4(Jxvt*f?LWF&<3tl`lQQgL`-24`X=4 z06oPmngV69LQTDP0rUh;P@{7iQRu3&MtbO*#Tv`mN{ChjE6Pwd!$dUMx#)A8iG(+n zn`@7iLylW{`03+klAW(AU_syQ)kav*_l`-NTH|;!#xcP>8A#7Oq~xkY$2AI+WT2&} z`iwJE*OItoe$4P{#%@H+L zCFrNk{x!2zW{OdeqNL|}t?q5?-->^HRSL;4Th_uZUloPUP&))d_T?P`j>oeMv%Eka zx`^-J!{F{cgz*3Y`|3fA|L1#ujgyn-!cu1?gkbjWqc7v%{15*V{_M~GJ^uTD^FQLv z2lw#Z?|v75`4@jK=jOv7|47*7WS+nGn_ovv0@i#%!+MOI2GhjBbmU_?iqX|9X@_`z zmZ4}|q{$Gg*}7v&Xf`OajC(7=OF*~ZA%fo} zuxn4589E2CBd=F!KLr-#krhKGJVwSfp8aSDO^&#^l`Y%f>% z1~H{^m8{A8!e-;FN789feSWOa)tt2H{B-b{}#Z{1r!e~H7z z@Be4*q3@FFZVGO0>VxkKl0MCQKe0~jVc}opDC{k{+YH@)DX;d>$wIY{>wt0}Antpf zpLf%1zVLwV4-l;v@M7SCjPDHi?O=d^@+O_P3OFklr>ms^`eb~FUwii}xO4XiPV57T z3vWZRPl3AJpe$N+Z797++JZ8B<~UZBR|3MT`9}K3%wCx7M{$B?6k$3Xi6=JM&*!rX ztf+j&9yb?T-@}uWbA10NPq3~v1Dc=DFrAF>_QN-^UR~hMbRvL0jZ+*X{QMrit0PWb zqrGO%V%rjKEaWN$3OBwq_prddd%u)4e=#L>&1m#~wSZn3iB$qRHSMj{Dv50Z6m21X zq8w`hIA>EzN&k)2u4w3{D23*sL=mRj2;nacS8}>O_Z3a*!i!~#37SOFHfIa5~ z^<82d0}2H{1$Y8FFOi7$2!NZ+yi^-ll7wV_n+$rE-VF<$pF@s<%+tf&66ty`l;Er^ z8ab|#N`|ZmtP5=N3>gC-5#rIdiv@LpE!P&dPq<%FDd5;x6k#%;ISoHYIP%-RwghZO z+=##~Z3qfJiTaT*1!*yqM2%k!^5za0kEsm9Gk*w?5ECfVZFqdya;zVP=|5C}l|a9eP(;!3yXZ zHY-|jRx+X!Mk$hX0OxRsQIf*z9jqvX!SZrbp(f#tE@xeXP0{0ffAa&JE;4vQjOAh} zz1~L;-^6NuB4BaHWay(L5GOT~k2vDgHS5drttpL*l&Lswxp3o4aJE3c3+Q>3Z^4^? zw_j?TDN)Ib0KtHP<}_Teg@i?$Rsy+EGP8sv-gh+4u-W1;8A)Yhvs@!zlPFh<4W>A1 z$%H@wm;KQ-Gda)n!`BFdM0>{_XW;>d?DKR4XFP#7IzTv`ARLeIw}1NtfB7H2hxz;r zY2+hGLt)xqTwF*nL5=U(>;gvz2e@s0BDQn%`kXGhgoo@PZvNSZqU$x4X* z+&E%pti(gUpP=tVBN0a8|7i)EOWD3b!Kz46p%i@p671-Ns_g&*XKPB?l`-nEvb=E+ z7~&qpmwb|{*$*GwH+u|P`u7lXO2YV^+p@mc3!63)l^EN=$Fk|9hfe93i%o%N*#^T0 zcj5WkQj%cQ_yg$wGyvLF!n+Q~_LbE4J^!m-a=!)ios60B;y*N?U(MFP=z!h?Q>4pN z1@vKz_1eML8Xtf7Ai^7WNkaN6-^bU#`abU7ITBHdCg|Xt&fua%Q{|}g z8f_JzqtvL^qH#+xiXfop>s$yv1S~F?6rEv)p1yepDfPwUC?307 zXYk@7{@tJd6+V7`CM<0(uH!+9w;tTbW_BVo(04~;93<@3G8=ag1xk=&hHgEudA~{7 z-H&B1T{5KfX8X;oyi`)#UGOXjF+*=yF84hQMneG?E^-V;gpo|pWw1lr+EmY%XY^l@Z0{n3%6$rLjm2osc~%0 zX6S4k$o1gNw^6~f*)FeVR#4=|lR%8^0;?2frFpw(DBIm+6i3RD5ya~XIWuDt66;I= zpBXqUh{?Rv&og|1C@~qjI?A!s&ME@6<@p(1rFO8a@K|mJ|IhuA>ID1bmT0*XC<@Us z3{lKi=)wT2w#RZsU47~}WH`w(9K8JyuBY~`is+a3`YoXAxAC)<+#ACSk<)w42pl;M z*FE=H%JaMLHJg7$O#yJ#*Z7qW%5cB5uKmGxe($9@^s9^Bja!qFlOFJ^%HmfK{OapI zi;~+-pSz7}WsdQ3AFpc}>?`}f&gZ=9Jnh@|KIz+iq`%1Zu<9Fdo^jeID3~Qg1-^Bh z;#(Y73Ie=%{sK$yf{%du5q7YrCFH3oTny;B|X+FGTee7;(uaXl<)G{PC1_GkAMDzLe$sw3uN2Vj zxUTeCjoFIyV;z-tB^irZx@3T*60i7K)nb9HDkaNKrX%=qgj&oodI7E>GeVlNP$HB% z+jKLdJ_EozJjYWn!$skvo2G9Ir#!k#*jo>mB4ZL{uc293dD^WOQv6 zr})uFAL55U{Ydx+ao`~KJ9tfrzTV(y^ko^{qNe#gUt?M3NX8?)^Zt8y^zOU(!{7LI z#Azbrv?41|WjU&BjTN~L^9y`%GRNlQ58yoi5cj+q4~D78^DgQhOWsS>5)Qc#RPqZW zyg8nV=6=EK^xm-u*2J{-j6L*TkD%+pmPo>3u@1-wYI+ke1Ew`OCkaSo8$@uaB-pSk zLy?+J10u0URUQHfdZ1ew$@HySi{@p8vT9M#z=k7b=nxrIJ^ik!dm0Iz(ueoi=dOeR zCwl5mC=$nu%?g`MCN`vY!M0lKQrd4ch)52G+rF&@5PER8oX=oO#Yhh8Hnb$qdxbz+yPn%3=!c#!fgCGZ(}O8aHfu4ydG_KAotL1EA{p<@T@MF$@AHJ+xCGynVeW{T77S_q4~GA#nBsgl+C^sK8a*5TdM{h)>S4#CPavptZLmxPtsRM#&eH4 zuZ1licn$_}h&YKbznG(^m$u`gC?VeQZaNf+TzbyC=>Q)-JHhuqevaph4NA(966Bf+ zU0dQ_d@O(`1hA%-K<&+k5An@!eiQ%b>%WG&#OO897vC4P+IkOWnSMTK!Xs~YKls6hfkrJ6)W_0*_j&n?Co;Fs#&lRCp;U+gMIV@U&`MMa7vOgebqZx#yJqc z7hBl2Llvmt#ieKwbq;9L>N~K)Kw0&&C$9mWqkmjf3Fs1Jl1SK;(kEx@XA{slc1CtO zPp)LUk|FDP@LK7k6Htqe(+DiTmyD&**^X%GXX_m6lEy=-(xUz;Z+8RevcS74S>YI* zY143N=0Ylg#!AhZv-B;k8@dK2u~O1&8WB&DMZZ?hQH+TDMj;|{99ERZO$HcG=2*85 zDks3p`2wvUz^A1#NtCxde$0S=(_z1o;qDNY`8I&QE18vLWtZ@a&ipsIJ3m@LmoEZm zSzqI^E7LWb_*z8wBhSzkpqKFApkMnkE>;H>e%^EOCqW=~rx)iJQW|{x_yOL3`UL$^ zA`4jEHE{ElNR}Eca+z1rgrpdU83n+%t(lNJxrk=jRi=7@r9Vaj!>KxavJqPWR!% zhxqviAL5t4{3YIf`w7n4xvFY(qJA%d00BLn&5*BG7%t8*IXlPns~4zeGuU+wA1xx! zMi_gTU)(`2Uyi$6$G_%audG8hNP8kce1NrvnI@ z*4R?7wJoXMK`|5;Os+u>XS3}96QD+WJFAB_$oeky>z`Mup-&%aFt z;Y|Sjy3gMQO+QIMzYUCc0s3`W>vezosRBCPmpJuJV2=w&7J(vc@YHSar^x_=fsff_ zil!`Z|NbG~d-66$N3=OrQkY$~K*PD)TxA$4ZCCQ1EG^p9{ichSAF3WNEDR|f+heJ? z#Q5S=k(AgcUZlvYLTpxR$3;QWjMZ3J?!SL_hQ+!@V|!w^IqU^kuNHWE?@$2!aL^M# zk3Abc6}dbp_cSfU!Ru@0oK2=Ky-p42o6PCW2)Ogv)mE7skB0KFr*USZ$y4-|VFe8O)=6t^@jliNFlU#yB3R zoEoI}Obg7GTIjQLc(#W)NL1NJQ&brG0Y<~2v>XV`>wX}Xvq=l|z)?mYmTw`mI9uHy zW-!A>1Oc&ul&?9V!0kzod6QIDD$*N+qs!}sMoR2yks&WitO@Guf3xq+;ImOZYEj_h zcw4E)4Ef-Fl8R%h$-vEcqbHLKQql2D&)k6e)l50xN3}izFf(+s?hwpbH=yjRt##WK zSx?Q*3rWsW_Z!W7xF5;|uTV0^T5yMeE^2`_rF1!BY2kv}`%VC7u!r(BO6EVN4Bf2Z zn*hGK)?WwgyIKNo3g~YN>fbk@Z)@3G-*w4-JHpup<2MEL+rV5FX-z=6yg7d489Eop zwN)c>Y=mo|@&gopi~H3Y|7BAz-M8Pu(Srk7NXoiIvA96PQfyY~ z9wwE_9Iy$<3}i{M3!A>%J;cKU_)&n6R*qebvzISnWlEZJI$vO!rfAs1^c^W>7F8i* zR-b=$CK);nC%A1orzJ7%I2U+4+E+dFVIM=XsOhN2S#w9t>?V;a7fWWXNmr`GsR7#8 zB~h&rZu;zI5pO-Uu*>hY5)0uxvDpSk^UQf+Wg~Y8N>6cGKkoS-wIjZ3RlU#&A0q1!Z`=U9q=J1~_Z`HV_^hOSZ^N_u%+G4j(^&KkQvH?SniM!kO?8 z{D{phbFx~i@iR^nn9Q0PH`@TpltyXtbNj2NgyZ;<^_!Lq75I$!O~C6X7j09t#azc0 zY}k0T>vbHtP8Nl5Sn047aq|4-_^K4odrWJ?tJ(QnjEVT5;vET%yly0N$y7xg3&CzY zo5S^D)J}kNDl+n(==IS#0c@5TZh8FB0o^E#-js#!>Y?uf)Lnr7O{85nFUPLW-%Ktx z@yV=Dw_aSX9GaYY)9e0&_s}wj=EjD*=Vx#-mWVBkCsQdOO1ZtNk&#K9=c0-J*_SWz@#im5TAl#9YXiN=5p}wI z!+ngBz5x0tp^iJnMwk&P8_qaX^S)+*-W(BnGg))jqy$6<)W0q72<_s2eZ^wry z001BWNklG;d87c$oX*9c%lF{|Jj^6Fl|6f0ynw; zHUa{6QV2x+N#P(>AyB~x@A-7SkambvaC9I?Ascc6Bx`S!mpvyF?7+ihI)fkfMSgdl zHOM(j&)|!tdzr4d`SD``bOU_50B-wry8v|;AnqDl+f@PB_4z+3K$k^!M+@D2xo#@k zZ=dj=T82(QPwf(YDyhvXAn9Y}ckrec_=}^5`0$>GGB1#?Qz4i=I6B0mrw=d~3}n`} zSdCGqxtOmo17q6fQ2N#L&@eLz`-qbSX`A|trY)u%OvgCdl={Al`7A?ImIy=?MS+L( zgB?rCw0<&D!3fpnmZ=E*G@1**tg_z)@;YX&1U6ykJ8FiXfyBZp1eDmPC;86qT6mNy z6%fo|NAwR@mZXvEqZh~UI~zGcbGbsiXCrqy>_2>{yv9={w34$W!(e8SDg``};e1c^ z(0Ps-Jdy41>k&15Zl%&f3ta8IrsmF7nVW!bDk%og89Gt`CaVe|wQ=l>E`KYk5jGua zm*z4V*5oAc`gTfihyd<+0jx-S0vP#Vmi~42E+zk#_PnetFl&!g%Y?#88q{rHjWNnG zF>oW8lMu&iEp}sS{}qXEEkMo@#l>o_goH{}Zf8Iu2?yH%X(|Li21Wq`@S;M{+e1l@ zfR@(1ePj%-sGrYk^AiE|>p)!vOE){6?E=&{0rcxW{|?ag&36+3n|sqde+TGS-`49Y z5W86J1oX9237}ikQWk?Wuwji)@fY_V<5v%S0qXT?iKZ%WZ+|3!zPGn0qc`<>Du7OF z)K&~KTv)yW^Z?~R8o!nT7L17dM+*& zGg#Uv7m!m+y|lfveQgP7JNNx+}f%nYZ&gNCpelN-!v7Ls~J|S1@_`S>8-Li zABB-(_LDH?yOPO~0LBtAO<@=qP&>Zsd?6|F_m!6;TW2!w&Y4w*z5233OTB=mLC_E2 zxPbuudbLK^Hi$h3tb5dDjwLKqbXlu%48sWb4vsKL1}KUKtHm15zAH@Z!^aQN?+;O} z$rf+0B!G1_!f7f7JG=*|EEh2Fs$2L?i@ul_e{~69=)Y81trgF4tHa zn+Qp*Y9t${ge%V{!Ed@)ioOA>AZy-_X)2Wq_R&?Q&3i%3!npyi{=p$uoHSve!6@b@4(PW5?H!2tA4fWjDIJEot#pofDxAri3;3AwZ zV5cRD@dWuQL&aHa%SJ=ivJ=C8I23kwSJvp5NqUa3p7W-ZfB>D3i{%`(?_)ZhBX$BT z^R*bl*u4-ReKp2>GROJZ6h0NiXw6DyZ$PO|8;|#f2*Uuqh!&kb!oWj62;q{5B~uWJ zR3u|i`oRTRl}Bx1DofU-fY0btQ%iI_g*gkTS4!Ll>6!4g$jqi+|Qovp^^WLpK*?-U1t3Txa?S@_7d zGh;N`zSHh(WEtg8wV94&veYbhY$0T8$%6TLRNzxVoyzPEl0rbVCX>B&;oBUu^Wk#)919FPgmHjD zMAMzVv_AM6Wh!ICO0;^MjKmSc)kK2gLo}kO$n(pfFE47GpPz{ptd!$3sw=K>HknGh zfUPW!H1gj(UE}QZ0#Vq)4HNVZ9^iDI3mMMq4Wvp&X1~kf{aYTpGRW`x`CWjz-BP_R z+rH^A-{d{7^V(hKWOF|@GyLn`x9jt^d)#mG*|KJB_0YH9|Fs_a9iZQ?MgKzu^v){b zSPlNOqkX*9>q#bhv0S28`*=S(K=OEi^l^;dYAwXJ^>`xkrJ`j`X0j6?3S%t$q0C*A znawXRWk00^+^XJTu_`f1Q*;rXx(dW$jP*LllrC3+gTMOSGn}2AV>+Hok9O1_Afb4P zP>Wg(=plMk;0l?g`shWWvZ~wwbklzo@RboULvqsnb=@B|KxqJ$q&WUf2w4WKO*xg@ zC(v$4mzvVP30#vwAXz)Be$3jX@{t(2Fv2-vPocT;v5Z5Z1^F6cW}~_s7R>X8(}mYNPB?UD&wInT?=W@ zb5wbo7Pq1Y&}!oqicXQ_sCf__Y#CSMPnMpU6*u)-X0oLa(^UaER)iJ`Onhn-^G3r$}cDrI5u;GKdhzeN>};c${_ilxBc9ptY5h z=Si?yT+DI4UcgBr=@SQDpd?9G3#^+4fBn(tm{4BU@?cvwMuQ>xgB}(O{;k9PUV<

  • {ur=xSu{t3XZVaM zAH}q29Lna%Sb=7_8uHlkAFn{t)#n9n19??YY7fOOM>ICq>ho>>z=eK3#{mfKUuc|QdJ{WB9gT~f3NbU@( zHs>`ptv8lpC!C&veE-&HiF?8L5gRc;vVa(nSI4E@#}N_4Ir@lgefT&~;17F)- z{KJh0iX)S*2Fj70TTS-T(|LdscA}i5&H*adt&WM$Z*;YG7W0!`tGT;(%SR17A);WH*3$4kt3!3bTDc z=N-tV+@pW{BQx(s900(|1D4ICl2R-3BP1_tKS+BgFbGcYQZkg`aUC@?9`3V>&#y3v zqkYb$TZ*2n2Qz{;oBMWIU8XySw*|)LxgK4_3tc+T!`_L|x1Ueu+;4dmdg9?sIr~q> ze!RR}nHkk^U+wlEa~7X!@`4|+(pX)tR;~GP(KM`c!OM7tUlX#?^~ig+99dA5t+Ksb zG-Af$t05YL6h7Q%R&M-oRTsg7xXCSsRgzu7wWh0O_!{)-(6u47v8JkcXa$3L31fls=Fhy==D z-bh)YQRpR6%QC<%Q9W*rEkuye)(ZIZ++C%kKkB!&-bub{U>*D0@-2RJ6lwruwtG#P zySWtu^9YPv-muzQI#8yBGINvq+|pwRN6~CmjT=ow!>NY=)!E0V!1kqu=9-f8c#Xup zN^`yui>3|q;Sgg}1|BPxLVKV3p_&Ue?IWW5+l2#$i)?Arp14jCmnEOGrojA(VKdo6 zWCG)wOB74vi06BPO*(mvPX>_nGa(n1U!0)IMofD1v2Ue~OZr6u^0V??HnwQX{w(4O z#^RQSqT;&jPTPk~FP4?k^?k-u>@e-yZ2j5K9_IbdzlM9hok0HE|L8OYi=OJ=bshc5 zC}vUolK1DS)~}n}P-Ept`CUIi6T)r1)$dsyM${elN;Sb?U<;ZXbbSJfQ10SVah{q) zRC3@s0yU>6a@aI#p)BDfVi|IpmYZWgluj-j1)f!`ZOX zfR%J8@)R7Q%CkGzqWswd$GyHzf$RTC&i>b0nmsGEDeEy+pvCg?#A_dMTNU_a`b25P zW%j-R=l0ON3+tw_D6Xn9c*I}-eCW+f`KUFp^mUZugNvcnJ_pQtyWfyjmqi)WC*zIXRSQZ_)lb(^G`V&kUmaO0G#fLrK{;II80AZVp@g9vJLX<8u4 z-0zezzHwEEX`EBKOkbdR{|9`mIoD81>=7#-rIsKH$*`~AHLc$twh^_`h%`Vm3r+?+ zqhT8KNG>~eb6JXyIx3c%wc`~~SktXp|J8-B!S-4O16Jgxq0@{n?udqU@9J!K?@b44 ze+t2wJ=dNw!&5pJ4(BfR+l}`=`o@Xd$O!oZ7oPLFgTQ~caqWeGa&wlAZ3kE`-nisG zWXAMMzOVc9+j*=qJLUU9-UsDb5;e0kTq~X()abmZU_Ns4uIf7tjx&96nSmmIcyqaV zJlfFaYS1!$bMPf7iW5|X7H`gmLOk*-5n5AIsT0^T<n9z=%~=?v#@=KOwJOToPK zXr6%O)O=#ng6qyZ&1(&KJj-6O-r{N8I70a7F5nU4&Q3r2)1JutputdO<4R>O_%6Ma z6dNe*GY@1GQo<9Ow)@mYES<>F$$tJjn~+7;5=;E_Gk0!;Sb`m6y<8@C_xY4ct%tEq zZT+H0NxGCsIN(?XTrp=(!kYzEb88Y|fEh z=*2K=++FRRB1lSJRt%aLWpQZ4!?zoBrB8ySOdO|wGJ9^BC%REg-*>;4oAu}?<^aYl z=-K)yec)628$u+y-{}vvKU4hCC6}gA&6u}1ab8D1E0cXw-&y!!3Cdup+P&#$YthhS za&G?wAqLcsG67R(fW`*B{>U011$4#jvg3Z<*t&L}Ph8H#>GEe^{^gRN#s^DC+3mWg z)+*vpqfl19dk-&8P=S{!hwa@{qouao6W8kc8B>D&3C4fw>=OxvznubaE;)mfKDd|l zFZ2HWj$0E$gZ}nD6ydBWtBX13f@xn`&rK-Lll6$|K+7JqP~C99`Q@`$8l-(x-@{K*8tmHOuyZ|;t{ zH2y5w_k3%jVJzbPV7!6&(&T{i==D5C3Z0bPJl#xomvWgb_gE-0GBkd_1yvQ!v3y~r zuB%&Hize`1@@ju&^a~%=?%fc+th!}m_2hEs5|Ev`t){1en4L1J ztm})=eQ%#N*>qz`J*3YIa=Eoh+R3GU$Oov1HnJ-*WxSgZYU0OvvCrmjRbo2BQbb*p zzTG8-9ZVq0l8K9v)3zi$>6vf*O^@G`$U8`yqy>Amm4~+c5or(T8x13U^>M+%;fH%2 zCK*jpUiLQg)%#Mbt49L^iUA!Rqpfx|Q%k7%6I}0NJmJ=-7MN$-$1KK=d2NdlIJGzI zXJ}+i0(#DyL+WTGU##&)7Sz(jLzK!mgfgmVQmMADOK^kUjX1dpUfGZS@$@|Mb=KxB z(4Tr*lMgjNtA45eR+zf|H@w3%RDo_j^w->1)U9jRxE;!~9$bMvjzrR{elhTaK53C1 z)s{KXb<|*cEuy2saYiRK1=?J_CuUJn2@(_8Nc}C%b5cm2>iWLF zIOgqt$|am5q+q$<43n%(O^~JeUuqfp?BP7#N3|}$_#Ro&x?KpC`%pFh@^I*-{0CJJ zIr%L!7!6k@4h>=lssgY~K?LBeS~eDHPE6T_D5-NE2h7;q`#ZA4-I7{30J1kg`@ukp@vMk{ z` z0t+wt@Yv6j++9o&{zoR;KWs_6Oig)ha?(Q!!IPesJ+JWmwf_viO5R+hCJ!`#gj<`yI)YQtQedVn#pnJ7=d@AmOnW31LCnh?E_3Z7 zLD67CsB?fA&&8;N?%>y=ok2_6eXm5#^>g0V$5axP(;R*|Hn-DTifQwTn)3Dy7-ZD7 z1-%`Ba7bkt@`~Q;RT{tbB=k%le)TKnor6Vv^8efK6(-vwGy4Tt>Mp!FrFZ4kjCOI6 zS-BTmcGjCO39oYQ%r!o|cH-QpPtQ%}<^A_6bhVKB{8^m$a(~n>_hbF=YsFV`rm25FK5x#KG>3UI!SV3{8??hNJ+8j$%DPbN0VRQynz1ep)Y=1s5czxX;Z<)Ob^}di#R6 zKR&M8x7c0YZ^i`M9gke6Mp;KThinJO z_I-N2|Ap_5pC9Cwb8|e-^|;1;T+b*SEmd+5BM1)V2)-doTOhOF&q)9nL z8u)g{L(SA1508%P<_lk4@4+7MLws*NRYkn-!^|7Ne+V5FG!^jhs^Up6Y>4m(=UU!#Ec9#?SQ0(mJ%!bnY;0Phz>US7F(md4p*sWM)OKukJ zAA%i{@xcho;I?+88XdRSaB?Wx9;s<1 z-BVg@w>M*4?2Vm2FMDGVge@LBy{>qJ@O*|D-bEPuU1G;PCFgz@pC5j8<8)=RM-LWn z`t~9vp5c5DW4K`6%S-i*3weRu`QOEkXQmr4p`JR!YM)U+%boM(;%<%{tuA zLR-h@v^k^X&Vy;??DXPTlHRfAoa2fogB~^aygfbF-@u(_`*&6|eExlMmEP{z!+$xS zVtHM1XnvTj{;c=<`yneT&tKAJLk9dv=W2s=7BvanPwIw{;Kk4(^j6BT(6dPe`IXF~ z-@!U(fpM408yU-KSC`U~0_^aFrAI(^{KTKIN+F@4pb2Nws3<~wJYoMC|0?L%^6J~+ zwEFXS$Nk6SMLN$N{Aiv)J?DvfuYVj~Nu3ZVj$o{dD-hol3NPtr?LOELoSYZa9z z9fB8eYz4jWqgbV0WN4>XrVOX3_!F!d?*oee^RgJX7qDc1@$pcGnY7@%e9WIZJD*k& z>Uhncd#j*rJZ1RS>PSR=;fR(~(6LUO`I*nwSXF=t?>tlK8_gn(Ng3sh=3R}}Q+3uS&M^)?ACo`%gC+zs(sFLj2k}qA6@$?Cg7mC}jiE!Nf0i|J-?R zH@g@WXy_MPj~{-HU1(H{kt!{yC^^#*@8<_F(wsf6U6`RF!^*^Apddyf10AHO{MAZ|X`z2$U`33pwbX4a1o>H)89*UpPyUtr{i z=&b@4Ew48|=lcccV>2DHUJV*s1=`D9o!E(B2SpkuE&VpQeB=W1P#uKS&lloQzMiZi zgMwiUjyayQ`|@Y&oVdmu(%z*bo|24?=HnTcihA#SH{|pnoLXx=D1Y;GH~89R&VN_d z=Xp>vcJaCzCD)kg)z91WWNlnqUTn7s8+X2yZWXlAGO#Z-ED(G;@WXCU3X`)F z6vr$z7U*6W#qEXJZ@s=m1*ZGA?Rt<6hhL9hUG4^FqvXy9|7u^)I$aRQI^JuUP==wz zqJN<3gT@bOa*7hN;#1h)hSEe`Gpw4Cj#8vIGj^u15hxe&9$u*KBnW!IYS?kDV`eNaYdM8_My^fFN(L%3lUnLGF?YJuVOt zS@D~#s@`|e)Y11e_&{LtZcpG|MA(8(3S5$(3rFeq>2&CPk>sCOs9MHC3?P;euVhVe z)7{n!IuLVf2*)oUN&4ZaNnLKKwdW#3D{`HuuvLa`1j^q&8--E14G4I{V+Ud=mx+GPCm9>f`@u1l;Vsq<*hqfqT*#z)bQcuo5~Ov6RJE-)coX&sNf zj6$cvw!)VmS1#5hT7^g-Rlb*ziypeo7GRwhcx;MeY5HL4yX>FC)Z0DKFLZLTlB~T$ zlmGQ|-V9F>wKlX$|Fw>a_s^oLy|vcB=0gc_3VFbsi&oCIXUoO$%c&Ga z$?uo}oeU3DY^k*?{`j;;6xvXomB-t$oFXUEd^*kNqLH6pa>#lycG0wY_k=@e zPPs_xXNRjAN1@UnzQxLm zZP}6l`j8ydK01J&osDROFA`GF)Z-}GLVt3~M6nf0%D+CR`f4>mlD=i&6xMx@;Ny^HecF$hi(a@0C->Q_;W%Q|==*Li+r`2o~w>2roM{D4N|; ztpblDVd?9q(-9*!m6(rFAEWiwTP2neBGRjOi6;CLbm*uY?u@U<(ip@Ixi6%44`|30 zQxL6UVbAwp4oh#A?OZbtU@Vs&A1!_+>4UvKy^C21x6W^j(jyB-?KjV4XeaT%m<9~{BFX{dZVPmnL1M`TmnU-OVi$Qwu|4Vj|a19!>_ z?%kq=gTS}}+zB*aA*A^7Y_j!TG)EpIjeXNcNP(s2%Ed_&s(R&Z{${je1op7LK#n4L znLWp^;xonKYGZ(9^k>RK>OCx-H;sk}NZgw~5dyx*3p#t{jmh9_3ko0d zmz0HMLp))Ux}wd!v=xv%0~$HTdq0l=s(DZE#1MrfPPs?D2z<<@Ao0$ zT7yAKF4z>vNNy2Z#nQ)@p-!>Nkxled{ytI^`4autQmS+DqGs9 zVnvcf@-7RA;{|LR?nk zZ~!Umj-GctuXfvIU{~Tz`U0m^4kb;Z+$`3N{{gLai^Hau0G)C{A zx2bM|uGwk&WI#~4z}$*#1q9WilSDy!Y}0W;YFTvzs<u;Hl%p(KKVlLylM4B)S5FY{?mUl`dDgy@#;mbYWTL z2GEd<%9AIVM}GqE*jU0A!~Y&jwb=5o+RUlqADd5|$QlLK*svKf@6hvh8IR4vUlu(|HWhW;h6k+>Z=&NA7kwzte z9!6POV{-+BRe}zEF}aRAt=B>6s+wmyHO)(xHqYZHee2wUe{OqXv3aA4h<9ooG>R`n zPF9HA&?88(=h|R#ss7~*X@%+HED_5kWjfO?*Po**{A}Rx%nsufdTQd>^yyu7K7hVN zUVMD8?CD_s=-`u8;E|#CZZj^cai?K`Hf694SMr$y$5qlxeHl(=EBX{5gN647DIh(r zJH1h|wfYIaSX6A%Y5@`ncOs`@v6FuV zLNp&um^(~W+VBrH5*x6cf8O}o7fYX2UcM4SS45Pg7fvYz>1nNUdyG!2b;C!O2s2*+wWBZe$^VhceYvKZe-!9T)R5(0THy_!dm{%KaDA(6Q`H`JJ3E3cXv!_zB;4K2zYAIP9F;fn)?N6q(r3? z_p+I#p)KujM80r9XCj+jXj&ehu_wI_2RCQ7A-CORx?Ym>aua5IY!cC1jF2%)j+9mP zF!pQG0q=7rB!96N=DSgxK3I>*1B!T!5esCb(HW#)Sba=2JCDFN^SJe1p?ShjzOMB< zzJsn0m7V^Kl{oT!HTdEbTiEoAJ3B*}{>ATbn`&|zR!5#e;7z;M@eS+qeb*Sgw`(S| zfKflTP4NO>)Mc#YySQGSvb>^R1!WQ2`1HGIH|-&` z$SW^{ubX|6Bo*=#jBukzBR_qmOw+tN00yDmyID`w>a8CG4Xxof3G!_p-~*WeRvNVk zJo>YitSzU0PLf(1U$tE}b{)R15%da9dCBtaB}J_pyMBS$aR7G6@q678$a^8=cGk2* z_Ry*r>5ann+cxwLw@0IE!o<-ZW2<_N*+d*eL1+W7a4(G zx9U%U*1(+!XS*RY>vtM92b-|NrM6bUao~OAJTE@Id)$0DwiZrrDOk~bY<5AFg0a_( z7rGWgw+Je}VbIG7U(ZL_qZ5(2cIcO{*fKnO7={1}^%@{N0wQy;WrmvrMXH?qsR*(+ zGO;1T0xwDvWtEo^2(Ihfg{M@VBS0Ub_;0H9lA^2ugFf~juU0#KNdJ z3@x%DZlqbP71(o?$h#^){QgoHR^LX8yIk}D=W+wc@?GOay_-BQWcdh133ie>bliC; zN&($_e>#8NkMt^8@4rC)wg0J^x^4~R=jdO-4;7VeH7Df9PAyB(e1ib;vHR~c&)kth zVTUC0v2yZu;zH*wM<8gId8m`7rj4Dwx=#t4_0z$_^7==X!18K|61^#mcI)D&>R^#;Zf-m-a_sSVu z{Rfa31oF#0mJc_dBstYpW?IP(2D~T%Xa=R3fydLakPj6tXZ_*LyA7M)*J>s$Mfkqg z6%Me`1MjF5XdRhn7bi97zuS!IK;BAlNvquUM9+yUzM*UtRE&Hb=GoX7rTFvC05{Y> zgosYC5WFYqt*tGyEsF7M*=;#raudCYv+ixB9+tPibsa{P>0{@!I*^yowWpAjEMYf? zqCmQuNCkNUq*n;|Gquqnw0)%&EzbWn)lLfey4I=$K6i_oG9gBOnemwq90F37r8PXK z`e#&hK4?_y=7wK9cSRo|FL?tz$J8H+MKF6srZfAzjv z98UV-VhxDl%*FZq^-dtUOI^oL;QVid%d9F|uNrRJ$BXWNxX2Ps$ zGV_}aI`xXSupD6nr~KPyfMlU*t-}t>WS1jn`Xg;mcN%vGm*eGkkVOP^`#?AB{V#_H zfiS%ipM%+95686|Yhq-Rgb0&g|K7NfoE#R~Le_wYNZcUklLWnz{MCk^eBI zxyXgTVZ`LZ@z4Xc4E}D*?1<^(k8VW>N;gFyRdOlJg$}=7)%5e0BGT%IUhK1ii_U#tQ{wN-tK-_%Oh5pvaSdK|_NcgNN7dI?=h-*70wJ?gC)SGXAQd>| z9frSguj;0|XB$r0O!?OfXm?ovj2XPR!nL~Bc`V$_Bg=q&<;jfYotE?0)m`_Vf!Pn< zFEOtYH;PrD-_2Re^x3Dsm|*Brui|F?GIa~0>X!widiU43xWIE;tB5O^IA9Lpiczu3E9oIan!c-sdb-$NQew=mif;d{F zm10~|A~zGZ6a^FuUjLnfPlL|{fliqzdpy-CN&t&V zVy*z#6366t$C=09ifqfCI9!n?9re1Y$>~8?KgHz!Dd5n905Wx+xf8t#q}nF53NGZR ztKqVre|^zQ#tNMxW0RXTBvvMQqBcZ;sX82cmi_k~dWaUUw3ZTNGqW|n<=sVT`7rb4 zJzz%e0rR8&;+edvpq1D+NxK#Q^@0e$>tX3#+B+&w|EVNgb+kfu;Rzy>%esz31!_xM z)u`7u&8h@qH>)4C8za!-aor0kaLV7Ze$SrE13#a9jMfc*F80UZ^&}>?wq_hrx#@PM4?#FMCKHz#UTLBE+FeN{QiCQ_dX!0=qDvu($|)?zv;Ke zKR1C?Mjgt+@tfLL*ibi;2JX&w|GnrJor?IDb8rOwR7h0-Xs!PV@p9%8t+xi{Shr7h2alX=t91j2U?r5yF`QrorpCgJT zFYfES@ZYX!Hd?^s2hW8YP%w!P4$9(Y#adB?T33R;CIRV}jDQ|J{5+I{^)6uz0BB~* z>XxD%ZnX9o=fu!EmhN!L`z!vy?0UR%a@9aZ!t?sWf@Y$yWp9yY_#1e(7A^56(bKNh zt0MvL>q}gt#wrvL9=(U9KAQq$cJtnPZ*?tws z2eI0}@3K#O<*ycd?kNJ=`MH${PzF-rA=~3ONTd3<-m{uPSZBQ_zvZ6eBiPe>xGe8A zX5ZHkD7BVkfrz!+k6+wHnt#J#h_MO=6ijuKYdDb`m5I?=@y7U$_5ve8%zLLE)6hT# zH4l1Ns(NpgmMhIsYu;M!`|aUdVYfDk$x+8Z1NejS9!v*Zh?mnYKo=~NTK^a}$Px2s z33{}$D{eP;IOi_UdJ-#`8tJI@^0&Er^J+@qReWup<686apbx^Htnm}M?nSw&$7{q8 zc%t(4(abf_S>B>Dk2tLv02cY}`{S9LVI`e@$Bl`ywQoXgn~X&z^8UQ!qhVz&T3@w4 zG>&v{Q|wY+rq~m55t8OV%OUz^YXyW*3;Zfg;x2wCsSN}Jj}aqKq+`cG`~dVB;R_&{ z-1ps^7j%kriX#0~M1v#}s-FM2VMs_HNxB97wHzR#z0MZ=o_-9piu5}e3yC?n$gpIm zZ(Iv~`~G4Zpz7ui z$(?U4E7Cb;*nH@q;n~$)sV}J93((Pia7!(HZ#hinqO{?n}Q37v%^Zn+FgMrt4a%->1(x97VdjUdPR3(~(cfDyg zDJxdPuQ~(z7@q{UuV>Y~3y(0!0-TnCAqGfs<8DjibkOyf4sSWt_uM{pry9BPYzLBfx`zE$(1?(1HvLwlnnm>6WxX_lp2>FY4UqhaSwC;06XvZa4 zszY#-{N;xBaLn6oTH`wCAoPCIcq@>~te*|63C(Q6X>)waAv*BAw9$uS(5J5`Gd&MS zRkML6Ipx~8jr=YQ?N{U?nqm4<$A+NpA=MB>MYsC06~F&-dpN{p&C+Y=A`K^s!6zbK zR^?l0ShqvOzGF}YR}}o{y~aWcU%}6NZuO9nDJki$bTe&c=uZvbwj=4cPQ(1$<*@^F zO@z*;HbFVv9HvYPDS@?izk-_R+-%KoJ|jeu%J z53k7=K3v;fAo(amoqLTRxfbhhI7rlsy7PcJP(u{$8Fk}cYM`7e^MKzAYQDM$*{(m- zy(UZ@xh6VtOt=cRyp1x|%XE@OlLcB%I81?Vm<%8-v8oOiJprRV4PtUegQEt%nj2Uv zwf%Ga9v_%HHU?T>50d@}8ZDx-r!YC;Afl89rqwVCIkmC_ z-J_;uq11`BESK+He*ey9MK zzFF|B>^5{7z+uS%>KVTbs;-J|$$nOb&t4DUC4Ee`(H`K-k!_Ssh%csKS$aIa}#ag3m@!_PDX|W78uzy^VJJ#D#))!DHK#l3CCjfr^ zJ4JyC+kZ_CQJ1hI_j}DBx3j-m;^@!IZWaw4R(!+1nZ-KbEU@C0Sn>Pyo)cFhj-Y~= z&hH@f>E4^%;H%TGr!FSRzm~hQt7g3h>I)rhBzY~XMyiK4hmd(#f109c*mCUVTsG~1 zq$L?N{|NSIPmbl?l+Ex{HLxwGWuD5S#hw{e%YaBvDRV@sL%4qoCR|V(bTJZes7SXb zsJkIi#u)REz}*ad@H|rFkNtj%eaLS0LxFbkX$$Ga?{>cXZ>BszZ6>NKKv+o zhss@*=Bb)UVBGvN>j5)EjFPFSUC`?6ULG5u;_G$vJfQ7;nI7=GlW$S~)#l0R$=A+|YHsyTz?WsRZ0m^GcKHV&)q*=tQJCw8Xa!A$4hd71T5u`9UN1b56=lO+-sqlWFlM!vTq|QXz6a>S5k` z%8+Pr<}&Bt-lO{4E51edJ+Bp4<6TsI*H|fq=i(|26k*eIq(s6M9vei@;OYlmR8Bl3 z$ba8T8x*CEz_;p*C!W4Io=JMfztOSjUcZ_)H@WV;bv@)?;}xo#a($5ADp}0=crwYu z%S%Xi>R%vn4pYHbAuv^0#MF&a$x~!mw+01^tmxj;(3HQAn3umrvjLR+pIiyM+d6pv z$oW`5PHo1`H7tPL_g(0tevQ1AjV0nHpuI!=3!&h`Q-+3%MGx(D9_66p!%cGy6A4#Yi;`Xyb z4OjBLuV&?2jfHW^zr)`RP9mZ{p8X8-e7@;Wm+n0zmY(e&>U?Y>oL;@nX!rARsuRo2 z*m@4m4)lUm_DJZxFM(8ksRl>n2@*#BY);e%B+Up+` z!g4TgZd8_XLKGKKna=Q!Ht)sLk=v41gh5S(Fa)JI)8BYno3wzgk?bB34q-fZ7NUec zA40g5S7`ktN!_2ek#?lC942G)$=;ErTU__t63v&dj+-ob4}E7nsRZF|G5igEu62ta z0^>GzImwkn-R4i2CwJM?6NBCX8dqH_&;1?~#mxJ>c(W(b#=q*+WAdZSwqzlnKYb ztV-Q&Z_`(Q#<$yD;Qs(>{37;>@`6E^+g@ zCHJ*MH^@AS*1#{glRxhluu+g8N?n@p0FWk~cAAX7yY(foM;S_Ti7Rmov)0V6%VX}l9EpWq9MVBOJSY? z`e?x;w#3;N2b#V{6Gho3-Ib`o(j(?ynl%JoyFPvDKR?9E)uW9(%QqPk(CgR|&4g>G z@bg(a8vsT=k{Q-}_Si6O{8!DvEYL?=R)CEipVM`1`OBY;DpzaQO(>tbG(bk{dGQc+ z0Q^mD#%{m&)TKG~c1fs90GB>gwvK%kWth~TCtE-3i=B!IJy*@A$S10wjI}10=XZxf zOO84muCDqLIjJ}8H5~v!yNkEi-YzwZX8XNw8)HO&Px|h4ON&C0Z|m<*U`Y?_>HV*K z`?%KY=Cvt|lv$YKE)Edndk2r`q!VwTeOU=H_U`GwOZ>H97sA-d!bZ0NBuf~ea0Ly4 zxB$VE`F5=f$g4?PHxDp3em+qy*s=2zDO^#H*D=RaW(~ z+Oa$NL;QZXE{w{`OentUOSbu;EvkO(1#Zf|jke{I+y%tHrswJ^AA1S#0Po`mCZtfAs@ZP=cbg16;$H@s1G4EH`8|N+u!t~k znK#$A>kR)>_c~7G>SQ^6=vLDNKcs_(be~4mm5^rM#M2V+%)DYB_izyXE}Q&W7C-wA z?WSJ3SZ^*+$5h0vmql;p#E!Gn1=MHRz-U3%HzNvS=OQ@L<*a;{)8Hbzk1sstXx_z4 zvXaqX;-8HJG=ZAli?i!XpuczYXwotFGY~tkklh7Afej7iKf*DuB@!xsz`)Q$qnvsqC%YBH>Xr5Dy!`f=UIty; zR4gg!Di_)ITHX&?ohDf=OG(u+Cpw~1DMm02>aE%>|Z{#B`%RIE}B;btx zYF`Ulo|G=0R@ay}aZ`>30g5S&*-BF7sbtNE3!Ir<>WG6J26Ow&d9?e;jOY^XaY@+& zYy5{tLync+U>lu*7Q1buUQid&{@2#eQuLJzie{W1CLkyIVnpj>m3e(uOndsdHJqzS z;j1C%?+=oUp2Xxx9&GnT4c-bb{Gt^1W4nGKlyne_l6N;#H(4RJXV*@hFJyO@7(RVq zHO{BAf=wD{Ui-r#nY_uo(w(ZH^#)>+G_H16PVpp8X2&G08dY8F^|siqSmEldmo3=h zm=U9{^{%JBGyA(@F&rw*((DOm%zGD`LDLeStj1>Kt{L;lg6>m!h zb5E`B0+s2v5n{7G6w0Xq`1MAi_xyk*h%}xG3)Fl3TNaDoIbz)qQ7{YZuCIprA-K+q z`FA_ybC9w|&llu7o^v&ylM9|$7_5^O*B=?N3z_`~O+IPce*=hXm0P!mE#;cdH`_fB z_gmL(-8&%L?$$8Jl4Kf3ny&-=jb*Me51!zm0i^tb>St32IR7)pA<${&`K-O%JNrk= z@dVhq1M%=B<8h@#avO|b+iLEz zNdJs)Cqz*zzG-ZWWKc~Qp{F~tL1E^BSPm!bos`ZCK-;X`=m-{kb6LUU!*<^o^zVyiK z#`}{_mRnSX383rq-AM>k%xI@!{_!dbLeZs>oKvFy0vPDRo#JjC-K>#CGc>zlsDFJA zqf16Oo!J*$jm|F@TDdn=%3|&?&qPWjBjZCbDg5JyXpy-hfV)&Zw_dxLrhszu7&;%b z3b7gOR#0($;B8#2(wSZU*Y-z^G?1IHHSa1$Sn=(4Ws)rJqh))>CIz|9MXR3STG`27 z&{<1_6T**N4l)R_Ud-um-^(#8C+q3zp9f5j$pi(8WyLL_2WISUufGyw?ZI3favkL# zu-wmOT3Ekr+Z{s2N(XY({_J>Ie6&6dtSW5}xW^bX6(k`3{v9do1TYJ>e@w0yEt+h- z%g8QTzr!jhbUifxz&!Ha|B6V>x`5!%YZAlf*b|!OU@lVobt=3j*!E#SPZOX)d<8w$ za4%Z?WN|+2n7@6TvUUv#FDH!ugoEu{pub9T!XxI)hq)dTgq;r`Yp|1~Rw+cN;lmxS zrRM~Z-TSOTWUQ`VY28;ls(!3V6+Q3%%_RNnG-;EmLu#^7Hg{fbursi)^i#1yK1K5| z1n!CpU*x37K>o}5Xi`ayI`NDMqaaBp18sW%{ z+D_YW-5eIgA5Fb6P_g%)`#-s`eHi|5dG%@LGjuRAvDt4t=;0N4O1&ReIvd~jZ&h2U zUM-+ZN^H?C&+J3=7C`t^?bWFZf3eYAlS&Ow8lM24-HJwqrWf2%T03PM^J9|aPaG|a zm%>wuAz-Y}W6t)>7P&|j)Z%4jQX{e11$nbtJy(FnZm`C(EU6^=+huTJx~HIBnMS4K z3!VS@-k81tKZ>~r+^f&xkH^DH8!=LQi*0Oo@j6zC&@lS>Fa6o5eFe7t9{!G2^X6+A z)Cn+0Ay~Xy8UZs|x&l{bHv;VsN_!e*y_Y`_q;gEd?5~u28i>x+bLbQceie2uq3?`3 z3_cz;u~B@?Kd2eW_+KR2KF#zRn!f4&r}D%}wJ$RDWlA!K>@XzHQ-K$Lt|iQ|pdQnl zNh84Vvjsv@%h^?{R-{C?m*KZ6aCh5{>q4A0bx)4-u!Mn|@*5KUTE>{U4-1g)V+Q%) zbM$;a;cF0Gckk2vC%UAmFF*nXBlha*YS`nIBfLdVr41-Rzx#udnTG>$e`|O4Rq9~O z!mLKq-|5fR0dQeV#}WN`y`Qf_6tJoM)|Nf^J*$L=({<*x_6j`%ZR8$JW{AnBVIm*0 zQpk6s1iN(9_#P*5YuCJ{Sre=Pcd9j0-C;-gH*Mrtl?TQ5iVv&braAd}nCG{^yv_vZ zLD~9amr_DnlctWj&uwO|Bnv(_^obT3b!35eS=%IYfQ=TjAIl1*3ub~@%Gg6!WQ_og z2IAfC^ni!JW>?+gGd1h&;f|yLD~;#G&(!-)99n$ zPnWX?v%6weWP?ZwkJelyKpHA#Cth-?Ug12m@R4;|JH-tiVKG2TIi&McTsWRo3GQCb zamd&s<`A&P3TQ~6YSSVT6P6@*^S}KyZFlLNkfnd|M%OeE^4)E3p`DzE1LEsR>qzrp zxJGxG9_^cG?%zo+aoD1Q|IkY}Ui#mctjkF6wkHY(Pe^dow^Sb*$i+P^t!5Mtk1I9miPa%wSj45Ia$T& zXQqNY6kp!>-?_K5AXR<#jCL|enyS3scPCpG-2ksKW(Sr>q(kB%?ZC zg!n%Zvr!~&eCto0kNrp6+9pCO;?M!u?dlKR7~LQpn9w_4XT!5K+2LEt=|Sq!BzDB%G)2_Aqd3XC zd9#lK@7ifg8sR-f^)R{5dUTPw;G?gAMUkM_eD!-Xf*$0+R*mx6N~ZVIP5~S{N^U!s zU{ez+FZ>|};rEY5@HM3tn-Xaip0T3 z9xJ4u)2p&BxRs~$Mvj2_Ou%pZR39R!E13JA!^$))d7)hpKawrhl>3B#%xo&bthU`m z#dj)PxVS>k<3is8+$ZB^SzzmY_8}6>!!arA<}XCUn&(>-ErR(KsAAdx3>SYZ$JwP< z_Sy%|c?QUf2EbM9|IV^XD)6p!oR&9akCllvfG~`rTLpjh?5m(=|5GupH2>k6aH+q{ z^6?=L_;VtK8BqC_rfWWt9d&@n_t)gfq83`5taE|Cam)6u%vR-(!w3z^cdQuuqBb$- zy@i0U0&Tw5b)ZFQfF!QV8Sc4+6f!e9p2*|4UA{}(k#v#-PSZ0kXCSP4?#2FOVVs;V zYZ;L0qS6|SO+|$KC7Wc3<>W5)b@iVm86~*!0ezpFINQIO5odUH`W;rP7_VA%|FD>6 zF*jxTIgv48ze#3q*wb(fxy0;aon%q|bm#1v@JMK$zemRRI3d-lOfxIC(E(mSELZwC%uq#!67MYV2 zs9ZE%0oSB3g0Ni$Gkk9PC{9ygKXRIf=P zx6(mKy#$ozx1h!L+ibJva+eZwh94O{@BY}$Kjhny`oNjuOQt$F4!8b%bSwDvCjn-l z7QYMoOgK@e?AFD9UMY46bt%wJx;>0^n6&WLG<8PEt9Dcyzj*s+mP*LN|0Lj~F|9Y# z+jgg8YOjwozV6?m1=EL@R;IZ<0iBMS7>4Sh8K0c_1&gIKLh!ltV~uhWJu=QFLH!LY z+B?*mH_yQ3-hSOI$Gt1qTSa}}irik1rioHI8mdjGdcbA3TBP5k)n?fN%e{HrX})XPr|sJz$$4|VB( zJd1lk@Gx2gP=4Y&%xRLo5#?o135IYyu_}F|1!5LrHj!aKV%{q{xoN7Y#VX*zA zGv}Q{Z)oAxLyPS^%C%Tw+7Dq~Y|B>zmmLFsfOMV-SYGO4?YMP!RLJ2th->p%ows!{@wBO3Z|S~A(Xxx-0Q|QYmP0dkKc<; zT8wYiEysONQ)U%-4ZHhZA^KEkH>bz<9#==b$i&jOv%zGg`#EpM)U|xS_hxiSh3oQx z8#=0f?Jg>md||Q6@Fgvp2O8GST0)%{j12R0CFxlMB+-FEyQU`PK{CCe{CF z??diGil(Z9Uu8+mx)+4&g+7T@1!?C*Y(C9YQBw}F48A;i;UuS_*Vr_c<5)+}*I`$V ziT?3CkrV#LD_Ru+UhH7A6S&(Ug?6QiW8OJ6ze6}-qP7}z;K$XS>aV`~YPd5@l>#3e zGK*u+W1HJ>o>YcNg!R=+Pe3I6((d+FEt;-9IA<8l1(1Q?l9E+LL5CmD=0 z@O7B|iS1koe z=)%mU++KXjI;`QFr}tgxrbo_+-!0R2ybxW){@Z_FKOcYXinEOw^^BK2_VAsI9Zbw& z!al|_#Mlj%4r&$lU_xiR%mw)DrQ1;wj{8O;BMf4(1s<-V~6ag#W5W90iA(r{Kt-QYjQ=iqnO$m zXTJ0ZbGJv`T`F*mkfljlt*u?2UR6mvTVA!BQ?yZPzv& zN?RqAxIU`cF|!}wg-aPd+B>F7YX%;D5_fyXK+`%^+9&I#VrX;FugjR(`QE?%TF8|Q zEcmh3ii((tkpXX+guTr>79dzpM*vy8n5>DsMAhL(?pZ@+eN&1)u56T>WB4 z(4WclNFJo=rs@8O=5U*P*ujxkkvZ=K3CI!Y;XFteYA9CT@|c61Cq_JH8^ zP(e%i<^CccSnx*veZ@q}HVU-KU8N|F`X|P#U=Ps=w;h>oYw6)#ap3JX1$xg>2N@vS? zGR%X8cNn$|4D!EnmWHi042y+;dHeqSxd_o-o#4F@`7k$2P*{CvdFbAIzo$$e(tz$h zHw$=+!yh{?+f8Wb=|7<`5oJRUeC1xtyqqFiSC$@*OTV zZO&@}VU(;J*{4NZCB}?|qPG-*&lHA-O80yg?4-)J+O%{zs~*Nv*k<)G6hG}PJOyv! z^WLd_HAjEIUV!wJN5t1Ge47d$iNcSnB{9`DVkt zBPNns`K+ShAIFn-dY;UL6+bn)l#Q=dB*~j!lgPmC?i;=RMliG#H?oDx>ap9Zm2Mvh zIrt?;#T|(krHkiI8Xf?XH`t;i*3tXg5R)_-y(bSm%6bsm)QY-U9^*?=*5U^laVdnO zyaQpjb?-V-sb)6~38{4USK#b>N*uqXS(P*DtZech5dNOGg1=A{sRoGAVbT>VuP|gd zC?Bn%b3eu#2l^_ILrgLY5oS&g-Y3-iUDju@rm=?@L-IOL$RVM@G^=5ErN0bDKItOh zxeJyc8Nb_^nrR0aH2O;5Bh#+W6d|^3+WX{*P??6|Olcw=ckYp|U@bf~RZ3nlOFim| zr(3thMy)NV9URsU&$@f@46a-w*1ou_C&bG!%A0_B++6{&w74$dZj=_qQlL#Iv*vo|IKC&G;l}$k&1gpQ+4K(d4A> z%%)&76AFNe`ax0h<2N3V=>#uoyT_kzY|mV1F;Riix{;NakGci?;qkq!cfjh5G{u{0 zA_=%h$_eF;l>gqu!TW+QuYreYhC2~$QC?H)r)T9sihEms4zk#xg-_rG2%EQ-O~R(B zATncSzNR1qDYVvk@i(L$LQwE9eR9uiyR!4{&Z(W#s~SPAd_=QeD#Av&?PyW#0io=n zhAn(i?f?x-RMg2(H(pobdhZCvsdq%y_xP#nL;fF0XBiMx+jU_nrIhaOlRb^r3iBV?1iR z|GWx?5!b#~9vkU#i2cU4+gLzq{wCs-5Q!JTXeo{wy)6oy;I#Gm7OX&tL>U$oF9c!D zfxrFAr0pq=@d-n$ct`Sk3yJd~4JLD5cGk|9QWA(fH})UHVjE8H>bwsmeMIJEb2r(# z`*NG%uC%>Eqdo7WU*&CN4s7@42LI9doXV?gsf7(wpmNIo4Y7r+>55`k1xE&zUnM%f zwvkQUewXxQi2CkW2N{WL?Bug88|qIF4#W8#H7;Zko{*13Q=9NBGuCJOO<7eOtdRmB% zry(zfhqlc#nI}J`rct@>57&GZpkMO~T{GWQ*n1+d=HSf~!P-kEpa12mE>@dFj)(Y` zH~Q@K2OIxWKGN=u2r)6~Usuq;BV>j`uQQItqR=(IxP#;073) zyh_{Y>zRdW4^O{X#524q$%o*JqO@$yqM-5 zPW`LgIL_%W`?YMgwsA;K`!A20SoQb?JMsR;lvu)@iKlF1vY#V}DA^pC7j&xaJ0|}P z#-6=~1qm73pKD;cj9i2x*nbB1FX`|oY;b$^ zZSW3b_*CqJl`#b{%d4zZe*2!@W6W6i_x>1ZcYsmKk^1RA;mtgg{|EgbS7MT6@|+<* zEFH_MFs+|=D}g^&rv81mYM{u}HxH%X4*6K{rUS((&AirGdhYyngz?!vzWfV@(OBbi zJALT+2KR@gX8%fBx=);skbJt&C&J3EFN1U7oQ)YhMxlx9>``?j$GcHgzd+ z;7I!lzm!a8SY@HM*a|)NgAZ~sHnN~KUZp7cKfB8eU z`9(f8G-_9mUEl-5%Tm_p{;Zl;g=&$~O*+t9;z#CxmctyAs>ke__s^Nas!x^Cpv}aX z5;fWsCX4cQ@s1<9CY&TKTzvgu@bXRyGX+rz$1T!NmJlCI$lq@vq1{m-9;8<`5H~Yx ziTTEM6?n%4>x7-4%-0ais0%ruza+eN3ho!Yc& zU)rA9LVpVpQTwji{@y(>#HWIQ#m_kWzV^aq1CFsGBd_ogxx80~wltd`tBra;^HN{i zAIQ!-AF1Dym38DyZO_?YhoxiA31BmM<;*2wDx|v+%3iH6S{-sM8=tt_l6( zwwkKoH6_|1{oyEquz-8yt^CczPN4ilETCe52|m@>_@IuBc8nS4NJa)V&Ur@TlC4kD z&IfQi284lfbw~y?XS7kKxTKW+{cvw_2y{d~`U7sXh|b$nD_oco$*`cZJ!L=yk1Q#B z-gkvAWMbc)nkNzZ1Q#FBndGan|4WF_Mn|v7<3&X)%j$C>wLD2ZUGVrFwM?s(G!Uul zyybK1BQO{!&l^c(d28D6sCts_#qCns$>%XI_#v0I(EC82s4^!d8)NF7}77!}@e<}5Qv994$#(pCbXCvnQ))5IA_g?azETBkHRWb&=`n7{Pp9eI8-JCYb@ z5L^E;WAZfHjE8z6<)LjL^UV+61Sf;{f~kR%)8flGO+IH;+R72fcr>J$tjJ0}`29*Z zi0*V0IQTz(58Ri*lip0y%&Z-KJeFtX`M#%-%^Pxa5$!7k?sqaeQ=Up5nu!@!qX@qq z2h2h$gtLK5h2Gr1P;TtAk8Jaae2(pcUZcN*{0A_1jyc5De8+m3U2J*BYASqJ-nD!? z@STmLqCRmUlt_k@?x*xoitcmbD5pCD9O?=Brg|Ax#(hcDyv{UaDN!%GIH+Te=d!md zy8VT#;(t&E6836z&kYkn0zw(cOuX_#3HF_f*d$bktjAk&%}FI#1-?YsV#V<24aQp7Sa?>p+JK3W>#H`y2T#aU5&Q??(smcito zi|?gwR$yH8up)P@nrWLOBs_yPbcFcvF{wMd6eA}fi(a)TI;wyDRHl{5{YVL8+VVb4 z{jx|8PqH7L)edUmX%pHCFzWA#Lsl{R8^uwX>I?UR<-}22Z{3fzmcg#s9!QcFvDe;7hc3RMB-DcyrS1VV z+Ga|LHtLcrk94du`=b8j6%I@M!XGheD@uFWeRI@bfj#}hZx z)D1})KHNX}L}jdcM-qu8ZRy^;4QudNM*72nzqr%4n7)P3x@k)oN zo0HpWWBRZ4rU}S4ns80umP$XK#EmsW9q;G^=|(hrB5*wERxClTs8RrBEcyqLqu=_9 zKwO}tlO27P*HbXvN)SCAU@+|9%-hNT_v(|m1f~D^L}d=XKk1AahHq2RdPm=@F}8ep6f;(Ux;uq5YeaU;)_1N9Z6r6X=(DUN zq)(ewT_WbNL@#x{uMcKzV{o$+(zf|o2T$6|m8^?sinXOKmkVtksBwg^Cbr96r3f?V zA}S4?)OuXEq-N$jTUlSr<-Yoe{xCN4WycLSK8=LcZd2yO{&QAt4qrc{?+J!nC7M4s zCD!>%myo@afC4|h?Y!f>mpCl`}B&fW@q##THiJBA^qTpgZnsji`GsBzpM$nk0zQveEFmp_IKJ=a9r zsf|3vz~xITGo;q%Y_~S#j}M5@w5s>vw($`5S_@fY(yo4wHL8OL7s_&FE7FVX2(yls zWc%3sR^HE4OK-whf5T)h&iL{dC7Q^Qp!WMr4IcD`3Z22!nh;?@&dbXZ>4!l(fG)5v z+lo$L6`*y>@v4}6N`H&&eeN7Ay`?V^oAuMvAAOs2hGHOHOdaDE2@l`Mxj69D^Cc<8 zz9%I)2>=vqCN*-dhaMg854Kt!dV{pUofmx0^DYSG#Sg1rf11qJ$*+DyYN1XWOZW<0 zE;B(W(1_Nfk2+bqz1+WmrrAop825@N@r!S2)5@Lbb2UB}x z?Aq}asX1`^_rwdY5@upPFpbzN>Y3reeoWcnddT$^O|<*t(GQ|9uq2ERm*fP@ zW9$adn7A~~?X}H27TPN%3u;juqlPcYI7`IvdaqJWwJmON%)C!m|GDlg^Obqo=2Fl> zaG8TFTR0rOlBtqST_A?#@*=kV5k2!@{*;sZ9L2Hi>>>W98ZTActmobLdXi6}45(@% zc+b6#Il8_1g*0SAHn?7-B42QV7NqP{wV4(pbR(`pc{3DF;3!wAl(v{r2=DvWnD~*K z!rac=W&I9>``x=}x{ZjvHq)0F<$KjZ_ifOJgf;cWp8AJH-rD?Lgd_mnq@BXHa(l#Qq(no#924y)^m61Za^Th;+PMQayPjzqkK--^;m= z^6Z5GqJ^xpFyqyF?cw34tyQY*(;TR9L>EO*B2B{iFdC%b2%fes)Tl0*?WV!VB6hPp zSKNKk>X*1W(L3Cv)aaXLWmu4E^(Q@6K@nk+@ANg6D3AmU{)ncu-A%c`MP580=OL+K zd#~k@MBlZ6v}Y;^oz+=HGOk3o!&pC&s(~}j`hPGGPD;A)?J(M5qw0&G8B+MiRQ4{? z0s7`K5YsddoJv9e;E=LLNg}wO9>vM7jgj;s=f&#kBQJ^Pu+h(vHz&lO^`NC?-PbVJ zm;{VS=zvXc-yf3VQQVG^dj$vokN!{Ckw1AZxsRpxU90lTI!nCA{&A*0oSNA9Ok_K$ z?=0h4WmpT!IulHO%QWdje#n3x>`$tBne3s=?93O|QsUh%f2NO+6=?Mvno2EH0u&TB zQmucgWmW2^nK(B~h!A<}6(XJ+jcKL$5;K8@`xzaJ@v+5o##7owy*yMC@_m!0RQr;& zY|0&&><4+x33P&o=Q^yV3&wp5Lxo1I(}5FC0P+Jjs<6ut08(D2<Jp%Y0dHKPh?=`F$}wzlhY z@hYBg^snrLz3zTodjYp>4!@YWWW=@Zd5Hy?><-Ha18ecf2U6&9s@aoI-kZs`mkjwS zvZ1tQeD*4aP*nJZ&hyFa$14qj ztk4g+yng&r&Xd5+M}H{CNi8o=ZA(G)SJzM5T_1fyOE>FBQhS{}!#lO+xA?-X@hsE$ znVA8%yI%~k2{>Le<_DDbb0Sh^!-ppVQ}4d%4*R`l)aiO#Zme}FuJhw<`WK?qL@cgm z+8U!G#tLpd1)&;c#advdU={{ZaMO02w6DXG6oNKdrtOknv?G@ul*K!UFbT@kS#uY zcVBl(Rovb*IjHcr(=sAJI@hufVw;C8(@=7}+w&46l&6dbYe21jQyx)wW$<0s^vk=M z33Q#gcLBhdbh%5RgYmjNn0c4DS?w9Mm$BZb6^GV?M8z6daj#GM(#cne(}9tdyT4^s z__i_Z;xt=7TDH=MFW?|eCNc-?N(5z#+LSp0d!s7l8a&>h7 z(|^%a_W?b)pcx-6d!W@uVb(VA8IEG6Z`4)kj_+GiDkE8___y~CoJQdmArT~TK+Sr~ z-TrG+IN~NyHwNQ*AxK1a&Knl-Vbh z_I;e`kBYbmD2NqOM!*2K6$tx+(JnxcTCM!a`>m{csN#D8P#lo*FsWe%HX(EPiQ$|e zJ)?|&Cv~%-Es0aSp}l!u{_3E7NC(%$NKzuU&1kO`kqth3p=TmtO#+v^$`n63UIZC7 zJrHOF&e27FJuvmoYC#tHn-}0lDV2?E13BY*l~9P zR+8vZ96BE^M^?6%PpJZ_ymr0>SU)p})~+`o90LK~L+2EDC|0b z$TSz1x8{3G+-!W~8Y+S zI>>@K?10ap7{f~NOZ`4Q?|cc|hN|BDOsnR=2=|8LW-XdKF;6byr_;L_lmG&fddT1fPmz+ZTb2>tE}L0H)b~!QaMRNG8iOq$oLpj zjz|0><=QoR7tjY&rru3-f&*|Bf% ztv{DNw&YELE*juAv9d7L&2G=eH7iw_D%?NpV9a_241Z z3^d91-f|ZG2{M4}`@k5=<(bZkLH{bMG_Q+4Cg)`W_Ak^OEgrXDd_1{4Re&Le$m(Pw zb$r{hnvnJaurq^SDq&KuFPf-g-`k2ml|-MgkAK}0g;BBd&MOVJ|#Eo(BQ#j>I_J&WkDiKu$XyKWQ1x3GBiD!wSH{9>RPb7KF~ zpg%j`O5D)0$+Dp6n6s)m$Ev|!e+#V#a~d-oee;?ImG6?itwg8x6}4M7$dGsj(A2mzZE^S4Pi;0InH;K*a(*XEdEqf)nI14;A*Lk>Ls176KmuoJpQGfrr?Az7i zx$jUmpuMPeTT*aEiD}?|y(0Z2fwE`lp^%`SiI>F=UiBMIvVEl zt04*oQgK$12R&z4Ztr97st~7ybj-^v3xOd_7#-%d#&KMJkY1yXEm4ey^h!N)(y5Bj zT<>Tw;ekF#3>!GtsRlI0$i(au7WW(v>llKTTySnWYJ0B2HD-s4XY6{-0TBCK?}dn4 z3hd1OwVHtchBa}%ek!an)XuDDs+RA8)6R>2j=%#1`K;zU67u<2dA(3;W(!z_%1lKu zpBkyN!)yDkSlF`{v63tZCE5rdx`TQe)L$<7er`kFD|^$lMqbmqK6;s4uYvB+y!x~R z;z6<4ir{(}xC}BKI^Od7KDmq9e88hu;Nb})%1&!Kk@bu!X{074(5i(w4QE3O>bi;L z#=&8~!yZyM{A&7PGz?d=7Nu3|j~}24JX;$Od^9fmePHL?7uiS$PItF>S#)jDiN=>I zYCk-%r`pw}8xEZuh1GI*-cQDm3l4>~dAe{};UTCfn@hKmNZ2%>BrF(a zAOg5ZlwHnWM03FUpV`eDqP!qJE3^pyQlFk1pH`q4KrRkR)aBT+QwXB+T0K;~76-rgPBL~D3yJ33^Iyywe(Sg{Td<9SFeU^S2tXB5!V7l%XA3Kj zLIKfP7CL;A`i)VMePtM z)H?S;v%!~+Ut;czS@<;mxQ)X@I6ij>r|awk2?}xENnZTgLgY0Oh|6JT1cedtnnMlE z!2^TX6}Vl}02!Rq&(>wZ3u#l&Xq%bAUfvD)EInH?qaXd#B5?MND05UW7X6QpC@X-S zH`d)TV2GlT0&pN^A1nE5&%^+pN`5M#U#~vH*-m_-ar0eu)ioGVm?6T;{6I`62Y(W9 zl`(J1v{WsI^Wf6|7KtGA5}s}-VZ@H?cO7w}Td83sI~r*|pc-@a9pY{~h8_z4`~rXo z!~Y|&gJY2&kR#=;ry-5)HURHu#jZ?FbO3o2Zn6)ovA6k0uYe0EXMm#0UZodF9Qx!6 z1R2v1H69_X; zrO_bx#uYb(Fx&s3wSaA9X5x$lPQD2WnY)Z(J%7-Cj@nkWTOhdaB?77dCudRmU$G0D zZDHBVj_b9U}tlTskV7>TPAq45*lj~oa zaR_ZlV_yK~cHjGH&Bh9c`YKmVvL5saDOU8x6no7uZoY&H&{TnI)Cv#XCh%eJ($v>G07MLsO^28N>N>lKW;Q&Rm^k!T7-|k^Q$m@=R zu-mhT~U4 z^#_3u(0MM>1Aq5@zsfHyw@i#RRIg-%TKILMgG zxd7uMc;Sy~D4`(XDWQaL9uoxp#)0f$g|ni%y0ASM{0&14VByCfy+!bpA2Erb+M2GhfV%cyceh9YN380X zKtQ}&lvMn0Tl9?js&oGA@*S8vSX4AjyPUmzfwpDx&+b~ve-{j~JcmBj5!nRbFy*Y= zZ)G@+>{WFhR=Qu#S$aOjY`e>(n0ftgEA5+0zu@NsH3SM+->xR?4CV{IRmv44Vnhn; z3my{J5kAesdn5*)r)Hni9YO`~JUj0UkFK9Lk2Q|QMnMFhduJ-N8gDN4peplMKT*eh zS5Hm+kYeOB7^Y0O2;>EE)oQs}v+h%qP+c*^{arcy{BIm>j7e6%Ss3jYzYLFDWVd*7 zgJM@C9z$kC8UFe6favh6b&$0b2G67{goLuRCJFi;&#d24;dkM*kxzyiSl1LbkQ8px zEVFrWq^@)CNYH@aLa{U7T;u!X@sMCYl;Dl6mh%>+21J7LAA*+!Aau2w;ZaXE2RUkj zN|IOX!q@Hra3li(fZD%m!@JIO9dmYFt!zD5dajjbdU~T^bWVZ zpvuR<4f3nOlTv%T_bjN(4J^tKb;JyzT8;--Wvd zMobhd9*Bqh(3Ay~!A^0RHas*@*oTQCnimMdaWxdv;pHn)Yt&Euv{Gu=PKd$D**tMK zu+i&ZHVJnSJwL-!UIIws)LSX|U(jmtf_5)S&uv0Mg~91j!ZIf(X8WS1pW1aoEK|t{ zIFF3;-Ao~cC;t$bXGmr`$u+2K(|F$3%xTMru`=5;B^45a*sVycxA$kh?JBqTLKA%eZ9tS-=!~q zdan^p61De6Li37>?Se$3q>a2Lu$s&x4YIS2nsc$AdZLrqvv5X1r0|ye=zno>Y=Chc zj-@jUIl73r%#(ZtopbcMf4eTv2Q{T88Zg$?5w8LIHS%9TOdx(e!u;0X@-DjSqIa-^Uwv2;XB zIdLs{i`&Q)=D#eBg-I{C#1-8&nRhd$dP(lbvxQ_#Y`o_nB97>w@OubTPE713>@G)z?g0 z*9fou`f1CCW-=!8)drr1qJm6dZ}iu-w@c9iMc-{r{P;SKdG2uCrpc4u|GPr4_FhOF zze>^k^m5)96qrsAnF09F`*6He0jYp0qsU&KCEB#Frv24e%>cZ=Rf$d+ z`)y2$va-Mf64M%B7Q6U&X5$*5y5|3!sLXWP%`Jpfbg7RGI~doI-5nAk6M(_Fp$fOix;yJ)Hp;(Rd7w_LP|$QBXjKU zBe6BBJRIj7pEG{z=#Tz(G*NZ@#X|$HN{(5+2+N@1m}6yN8Fq1qyWF>2tB@W)ug z$ju->SxFVuzxxOC)5bg?0H~n23GAyG`Pnm1!!ahslH&>`HK?MCJ+oMhcxp-Wam8+~ zm~8x+Zi!q$RoELl&8csD_YHWm=U4;X*KxZw;Vl+uZM{CKi5{jb9-h>hafajgtvk#f zdGF?f4Hv&1KT?9y{|%n*u$v1I4H>7E({xRK?hCJ3klgihoqxILVA2tJ10;JL{IVa6 z(`PBVbbNEb^@R|Bn00oP$@{oA20`pLQ#VgA4d`wJ9N3H=d1~nxGiJ#up3im0RY9RQ z*vp=M_-J`!&mqECR$i;@_^JG&9BL63+RN^D*d!XqIS#K-=)5A;8F*Vxo9<(%gXBCT zzw&2sZKVlQ%@nX%5IBK>Gh1SvNVP^#&y-$)h&Vu%n1($R63m%KzZ@D%<{f@$3Mtw< z8nHYtc+1toNG4>bYx>;j3lT_UMYrj~wOjy%kx576z(4lU;kncxfUob}GChPpnoAB7 z9kmjb6L1hR1A>l~3n=J5|5Z9)Ma(=e%xsU{%$O?zVelEukuQQTn5Um4=oZz$+gBaS zQkkYXGQF`sGKr>v!zU4da5-wC5?iT_>J*E5**{kvIjh7G*v+@s|{RFnnV4U%D|89V4`p?IcCOv-AtK`F%SBVYv%f41w zxRs6({TpJSNM0_~ClhnCnj_^9EPuU3bjt+!G4!!f11aA#7jzbxHGzA`JeCj? zzbAGm5y>rY7{1oRN@}r@O~*hjEBGolM8+=`J3eb-!|E~}y_aNtI|yp86kWCS4A*Er zhw+GV&snx|+wvMk7f>R!ICm`yBH+Szx^FQ|?imbn01Erd1>sMra6V0}Eu33!IDb|C zI)#7g%}H^F1AE3*Cy*FE|5xJhr$Fxx-2R>FvGY;%65? zJ{tkh*26IhIn*Inom2|M&a2Y1K`lq zZjyDxd4%mm(%7Ju+2qF?&D1I5cZizGAEqqGl)N5c>;AEGLt;7b-$Nm_uB%?kx^o~1 zI596pUF?hB(Et3P^}tZ7i9Uftt9Z$|@EY4Cl+xrdF7V#$En&UQpA&4BTm%~FrL45< z0_dK#gz)IcH;GJ-IV->$83g+Kp@imd35iEhr%}WpL$hB0Mgo@)Z)e?g9w37#baZtI zX8DYNHs5M8`pZrD0U<2&6?G_6AZQ=P81KzS5u@s?_nzRQ z5N9e_wuD{bT0I=mvl{xH^a*xGggk~#sak#l6u6k^v9>gx4l zLA)erVC-`WOcAJv=_1xss!9w;fd^t7jRGD^i1G+nX{K%wS^hf(kb>e7?USm>m`(MD zH?0WYVXaq+_i_VpVE5_%@dr1w%NsPC_7=%37%?jNg!({j*9Amr#mK1}HK-B5(93`oz zUMie~B#!X`A~pCkcrCib6(syr5!B_GejKqK+U?z*fx+1?aeeL)uGZ8AiaI;KtM`5G z!kBySciOM)K@dU}@v98ZXmU0KU=!~LNRwg0d%A5p{VSHLCWm9CT@lBvzWX&wbCg~G zyuW7&HCcu|Dt&%?J~HcQivqR^l8hKr+%2EKa3Kt%M{QC>Y_V8G-i2c!{iLEx_tLFS zkGP6dhqh6BqcRZN6NlSC>9GiO77_LTCT88UZi4k!eh#d6oLjM7t_nMX6KhLW*EgW; z+?42F-upN#H{uVwJ0IbP7cQHPJws7yuFO&9xoTnP8H1|1M z90)iDv)2HrmsYx1uulcD%MN}g;$A`+XT4qh2AiMYP;kk9@Yn~&0wFf!80OW?&|m>I z2x0b-lhKAz-?G#e8O);{*BPJsn>Sif32P*nvg_eprC(kG7e1&7v({hI;_K|W~{D;9EgYAn*(=4_vs97@*& z1!6XFYU&kb7ow-(>dxD@jezMQHN+3&m@e}f`(jIX%Pg@B@N@IThPtTo%7r7KI{fjZ z3O8R|uTO|wjVOF_A$l!BsTGEL}6g|_g*t-vl(6Z z;C-qjdU1^{%X||xBAh(wq^u7wT_(C&Rc&vD@CQoa2;j!WV#2B*9`+9UkC`a@U zXxssuc4lqRy~Q`nuD4Du@bH&JZH?OAiytB}#Z0P_cK@FD~-Bs*PgiXI?W^O#+ z7@0JL{M%86a79;-U+fjPiuINc?^A?_!QElqF`HosH(T6>k_wM z*#s*aGQA{}=W~oFDNQYYoF@$BW_Gou_G!M=uT~)hx80vU3*D9r`IgOpL0<8Tu6JS1 zcvBDDdFdkj&cXyt6U{r7<~0)bIQ&zpkDU&>aTUG>NYd($&#bp(G+-V16lETNJmv&t zdspolV?~f#z5vfh2#hk|AD~CLCh*pzq&C!MYjF`CdL8!fj7P>ysP24#9F&Z-9L)=T z!;^IrOnSdKh-xyAE(uX_M}D^jFoqxIHezb0Uf^=7@L;Tw4Hk%ev;4p&ut4HS&w{mD zKp>kW5;3c59Mbpg80JGne7FFfJ4@TmUP-50NDQb`mUSE5CPYfKO0R&bH*E*EQpI|DpoHr;dGNEb&27oPtAvGEsKncm> zH*mxBnptyY6b#<$Y7XIfogikU4_;js2ocU(yQ0iw&D_0R`I1aZ9&!zILw(^#(r1vz zwJ;kkvOazC8Tn&ZAtO79a6JaMX4OLi1>6+iy5LjDwECjBN2kunCZTkwl-|V8y{!lXDCL5cVz+6;U}=;}XYLvd%+KEB3w#n+Hobv6IW z1kKk&h?(XyG2N^$1xt){Ie6^S2L`$yDxYD>@HO?VlgMEv5XX)zkXAvRd=4cO=&gAi zdd34_{Cfgs1YzRYWjj^g1)tR$*O5)+ZH;^Pbk^#hBS2aKJpy1cQAoE6DXxNz7!q-# zh~GDb4k~J9S&W{uF4^?ovX5XDXUP`Zs!TUl=rbglrYRR6^rCXcU*McuboWJXRwbU* z?fzr5F_^==m+@WkigrVWS?jLCHjiF?PcZsY#KcypLkBlkl{@yjtKZ)BfS$GLl3 zTTC5@H#L|(^7@k&VEp$)kH}!_b?I&RwrsZ&s#qyM3EA3MD%6&Yq6)o}F|%X2bXDp+ zWBl;gXgq~N4+UXtsXdbqZUw~WL`9i#78Yp<4{8Phc-WfhDrxSmn90Ga!QdXkoo9HJ z6p7xc8Rke>Z0mNP%c+4TDZ!;7nmmoZb;y$*vu9@SsJQVWcPA`L%)ep4P2i9Q&hDo= zG6Ol9apl~qpPl{E9V%-XE5#ARMR<>OCrxxY^)>p0@9S5(kt{!pTjPB^mZIYKc}>d3 zjA!CH*WookB4rB?LI^{echYt>GWS-_KWZ`F!6Ib^#>&C6q*A`w4^;%lRhoOwT)wdn zhI>mi3GHv@KE-{%BHi~SgHlheN+tg`K2m6XoziYWB4bu@;?Vi_@}W*yrT^fqt)vd@ zW3lFn8Mn@5@H>~oEKGxv3)zdgk`u7`bj(l91Z==^2pkreO_{{Z+sX}n;o`gZ5htT2 zBy)jV4DN5ysdoDZfj_^zIoG;fqF*J4K4j0;2>@bab^jKCs+$AJ+^vbGD#AavVy30i zQkQZ6*^p5`-G0g2v*VHS>h0Ul*Y~sh-`kbv2$~6u;h)BMA^yQ;%}=w@{N3tCh4_UR zokCk*T>8JbBRlp399o$=&|nEog0gc)IWpGu!w2NeQmE_&u z@Vm6LI~{8QmMpi#47tB)3)e4vIrVW;5Q|(FZ5Od%X8?5X@R#Y4>khTf)4iaYMZkA5 zqB_Sxhjec>;HQM;W$TuxDiB@GtLjp`B`j*YI@)yT_8u~PDX*G*5cPPh_T`X~KB(zA z4ylf=hA)o|D*Aug<*d@1(Cj+BT>lxp$dbBV)6u(LnjHYo9t7g+%LVbY_3G_&aJtS_ zXLhx}h?Du(q&WDiV`zD6-;+ATZ$RuPSg4T!#u@G9@Q>y*x-6kJQD$52XrgicQ$4Px zG}}J6o+VwWA3f&G*Hc({*-jg+D8Ya``JMfO*D4ma7x9d05JpCyV5WKn$q-_FCo?xF z+0zjEYV5_&)MTBHgBT2)lX@&y*RIp+3El~6no@e@V91>}bpFX|G#WKSN9<>alJCRW3Xa+3Y=f)Rzlmu}y&uP(~Nj zWRrRZ&OcX-0v%7ue#1v)Nq+)4@{kk65(Yv!!sT%*+h-C2{f5_%%R+ZoQj8U!>TJb%9eMQQ($R@LuXx>E_Htk)p(u&5ql)J66V7A}O$G zeZRj-LwNyKned@)A{O}o`Oxw3t}8YDbK)DHe_MC=76mYVY%$gwYS>>eidse3VT(T)cW1wJ?{u$u*ZudXjoX;?Vi zCy%CYkB(1!eqJ^ZqiPVYeLs8~o7lFKAAQ+z^jyEZlT@%S8z;)u%FWomFMipfz@gnK zaP49k8f!4|8qPtvq&~r(D$2tBurLgYcijo)#TOze>c-c=>-qPi0YZTkt$Kk)COZi> z93L@1ln>!VDZSIFS_cfY9f|Bb8Ds^zJ?JD?>NQa7ccYHh%|(C}Buj&yTk{>S0u7uJ zOIX%fhZsx+j7-SY<4=13bjx>l^$=fXDRvJZBKE~NfV~<-Q}1xaPG0z^WADW_K7mv+ zd=-Img6UU#6(Vt^ASoc1H-tQM2AcL{jMuC&UW!v~!XVL^NkA)Cl=$cgXr|3Ac}q@T zm&O0KfTbz?92W*>V7t^hAsz%i%K^)jBScendwD(T6kuj2I2p(uEK5!C>{wnqN@o!3 z3bkMx)DL?wRM+q@jEb7XKo8e&`DU+ z%Fn3%nfCAeaQa%N%nOx!T^%u)si;jYA#RrpV63at9o3+IjZ8pC4V#^sP(_Dhhbb}d zbIO{bMwE%0^L`=XVeM5lk?Y##cn;wt(pqA=<0tXL1dt*1f$c|u z(m(j8-UD}bV1)70}q{C{@rxEZibAlnscQ&EE-aXS_GH&*w@(=+3JZIzQo0o12jV88^7$A~6^ zNHR??jwmqj*AI+kSOE zeN$bzku`jf7SVIN{^JZ%sS~4cW1do$d`_%9d{|q=MBeL3n7&b!5Z(uCHub_Mgsb*X zx5j7jx{iw2S~3Ie268)Z;HQ*naR}HTpBxJx`BSOsWX^D^{Dn1FXzs_j{tkj%8m-q6 zCZ=|r*h=RJZJ1~T+KKVW7=J&B#~v`|M!?2_crfW;{h-Sn;=S|oy!uHd*!+?vQ4EQI zAuFYmh&?~#_-2)=4>SFReWW&F{2HVECoj4In4TUM+FK{2tityu1%U?m99-S*` z`nz1Se;-f2GldJEy^}P_i)jV_{}FHf9$WKF-0T1_C)0kA8Zr^dVeleh@{7QAp`b~L zq&}sJ#>~0O_LFVwIS=#csw0ALlB!1^yXAAjZVL2bnI)=3pg|2|95{vC5ZH%TEnRYH zzxPIN`gVoo{|Vr~S4)>C_3slb2a2xX^W)67_pOD}2|p)daF?$A21dE@VKSrvV{L|D z0n^hxD?5=_9<&cXSmX84i*QV`Uk~4??vd2Ue1jYRK~%%T%ROEF_X_MvFLk%qR)@5Z64~?N_GOO2# zm@O6ku5B(5>7PFFX)DiG9q1oHrt?JC`Q4?Dn0alzn6s#1J{Q^mlNQ(2SUqEBOf-U1 z&a?CAwqB?K9<^$cWBFO~EsFQ&yyN%sJLGWwvA#l)_hn~;>RPOsY?XMEqPsp*O02@?XEe+`qOx+$KDvo zE$@iLaGuoVN+X8H#jHDOCnB=WDrfQeBd{09pKF~0*8dG)$n%B4zpb=@gvS4z;#0YU zVkF|PuLD>Vq_@oT!ifJ)b-vV{_{sm+77F(6endNj*BW3kKh|SbAN2Z?Lot%V#B3u4 zX$iGYnQ7nQm)-(FZd!|S?M>$2MQ`*97`n7~#l*oA69%2yi4S?l zq1E$$hkmgVLUbe6zoH|<-ZZHDF88F<_>QUjIRF=X<91(P->~|xzyG29k?EcVbCNsO z6~fM*GC-@kQa9eb5n|Ay$jc}_sF79dU>ARy32KEf4z}2?)F>ZX4k{PgFP^utiA|7qP{%5+W{r+O+SnHk=t* z#Udys8LOzhvT*rK_X#sRoKAQzwd%ds0b63hR)jW~L}bLM zsB6bQx*G%Q#kop4elOg;X#A|qbm(~M1I`SSCM~*K!apxfMm$EbB*iPb;NyJ-HM3la z9j%s`b=Ai2Z6gSjRIxyjNRFnGDqET^q+-?-5GM#Ix(0k1KeQ8*I!ptb8y{V)l-&Fi zx{w3L<-@R=<<|pr{U3ppZOHl=JskP8q>N2+HM8&Eo(3V06K;dtzt?-dnKavqCzT?F zltqU>3cm6oQp*`MxcUE)FJi};>Ky0yWz$xc;jM?WP*=qZ!U;@|1Rj_L82MK4h$)Ks zuE!rZTe_`{+I*s6&YbThpp*_UE?c?p}$lQEs6r#4#wL9U}??IeYldapc8 zyP8Z$A3k$2YJ$3#oSR9!h}}$&lmcO=ijd@rk^RU?$_NHeWG^S#w~X=6k_A1n(YOr= zMRb0g*PvH7C^Z;R5)RC+e-p;$sLwV%F~5sdjX;a7pobp6BD6d-F(As=yX&EOjMsZ| z;j0Pz{lS~qE3VFu#?kBAj$$d4Ql=y^{_W7KYkf8o-4};AvSj|}AVTbJ(g-Q6Q^E6P zD|mN&FB*tRg?FNEy$Bw6eQ%~0Z*9g?`2NQbRL3Q3%iS zy$8F6*Ql9H)5I@q!eZbDEgTt;m+tE^vZmgsTlN0M{yH*OxyY}SQ?u~P_*<8#6I%Sd zSLnCE%aeF(n4}>aK6RPax2GbHsn31@b~qlkc~#$B1EBmfvX{2na95=*YP zqqY547rCGs-{=5`!>dJ}r`fdq-96^^x^BT|nMN7Vr1kUF9QJ6o8&I8S9$MS-5pouK zu;6X$I~lr?M4~G^mQaTcq3~GiInZkl>Pj6V)~w@H5wc4{^%8$)m1O7{UgC`~!V53b zc~K!u%vLt9{HwUN#U+nH0!SbutR5f(J(l)xU-EM?XpYJVlPZE4HWHoT1vvmWY-Yn= zOn_F?C}O@SGrxV%J5a{}H%O~;#jwWs;?ultH31zOV-FQ+Qm0JCV>``}5d1`;gTwO8 z0$Mw!_@31VRJ#!?a>j!j<7v9k$uog#`gc(>-KHa~ZXdtL3Ec@uN3JrYuf83b97Uf< z_T9=eTF@38gZfHWhNu;6=JK%D_XM=Z<_U^Ea|GVToV#qR>qgUSrx4w*1(aS&S_R(u z*l0=7Tc6p1b31p3qAfE)b2F>zr z)1C?663{Rob9EI`7J+!Ge>W5EWaq`RN2ls+o6V#G?V2Xeut{gD2&&(!99>@t@Fkyg38n>UKkd2C+X zZS$7mr78OFE}B%5R#VpoA{2D|A@1lOZTk|joI52(L*Qy(0FdQ6$()c6Svok14Ox<(u1#tEEIW3XLBce|_xMyCf=*=z6oACoRKSklZ41 zCzksS+be0``p;kNb~3k-XuDE21mNwZ9fp1m4e`LZSI>#E0-Y{ss5Q+Ap9zBRLB>>=ZqaS)z`w0^oCeM?2qUhJaPqUh(zeA(!QC2UR8`|ql*EfCmil9 z{afq*CgQrCC(~tQWE0VBTkyR(*=y3QGG|+KT>l_Ud>>+zyqgBpG_Y-?SiaO5yE`{R z_3le9PcQk@LLIN%Vyas9BA%<-Mguww#1i=~TaOI=g*f54nT+3ru~!5$Tc% zQ{v-DMQV31KeS>uy!~$a2G}ZQ{H&kUL zNKN|})~!8lh{ugUdVN8R~IbKv`; zYeV`sH-X>Jei*=|kQDIqN<%i$^4sh2jIX<7TH~irxP`;`7J6}YD?DQl(Plwh<1+>? z`p^-3YbU7;C)!yFHds+4sr8+u=<~0M`tix)tiJHMH{LB5_rQGHHqqqp!qfAeNj+23 zyI*%XVg1HMMfycE=42^DdHzQ_b>ir%A&yC_eFCPsCA~@y@nL9h-{qgcCpF8m^>us^xXF3}RK{$HE!iZG9j{rc2yl5WFmB zX`=rRZSXTDN^Ibid>i;KFxoG2eaSlv+V*ltriDGCwOwe*?T}uhhe@y5V{IWvU~iLl zZiR!z;PVuZ6SGd#`8g=Gq+O%Rz~NEeW#oNqw3><0x z#Nwb@_APEZ;*~LjsGO737KlA8w**Ls`)G?K?ph9E~Cjv6d-Y)e9>`Qt{|7$V0&&TW;C=< zw7bN)p32|J8}=`TYT){`?Nu|5Zn7t5sg1RCds)W_9nqK_pN=Cp{`KY_1Y7kwyOA!u zL>hb^^!t1UEr{kyw|aZSe2^_MUBX2?V<5{sCaK-mc|a(zZc&P-TaM_@@FYILb|}Op zkZ>dgeFqwl*=~Jrb4$`?ZP^BuABtRxzu;of-LYSX*#Rdn z;;0pF9saN5RTB%85n zwI8&loO| zG~VWtgL+zhZ_od59-Gsd3Dsz9gbPDPuKB%BM@Vy~zQrh(>VMK*& zaFz#kY7YMz%pQ7>C!`DERi`B+h+&l7iE#y!{r$x7cb> zn_YH?xcSc{sz`Fb7awbs8j_9@Pm+sv_7+^B zp8NPQd0#;)nU@CMd!`+KrAX9wwa)bBxQ;TZ>phe8FX#Rs>&%+Ixup0SKfq5ZLe-2% zsYcThW)`{0>H4VK_bo|zmmIymOCDbWUs0NWgYz1@V$^H3w;!jPGsKiFIKw97*G;#7 z?-zMR{*X^uDA4{`Br+@pAuT;568w`lW}iqyeW6sL{dx9<6a3{3lb?D!B*Ee}Gq`v9 z9E74h{n_raL3XL8(qnLU0U+Zj{fVqw)Pf6OIy_$1j*x$jK?)oYcznGf2ZouD`$f7c z7U5mA8Uv!8hKQYkn`+C8p*pF1ZgVvpx+(%V>9%JK#? z&ULWS;?+jx-HGWodC$1|sCw?X*Y=e3P7Ejc?S9O#J{M{KXMf-MCKg_Z=DpYeyH=CZ z>M1hZwryd6TG<9K$qfHds!mW{)h%K9H#qg-?(SC3&*~|e23$wC4|-MKHS*R)2>XRP zyR=OzFsnV(&vDLQ?SRE&sC$3`4`n^2X+L~+XEPsR1%gE(-0!`d{;*S;mrT_w z?fWhbR-7ZuLNU7i-ll|LEe~>z&%L;|M+VrC9qdY>b*~;nj+^U{6~Hbzc%tY1&Klxb zKwGl`ZK=WPhzvjRP1>PKP>l|RljCCJBV|NYS~Dj;hF=+YR%wnWSBV1ve$!+W{TeWP z4>h5-3D^E7dSCycQh(H464Ya#=IK{)u0Y}6fWGLIDu4+G+Tzq)2k`kJVOU$Kq{e6m zrhX?U0{tOsXDr^crx_ONgDg8zw(?5v&d(xhA|oaUO0c&Yr`*@P7_S*ey?YnI@HZWt zZb4nBa$DYJqkr|I{pf-64fWjY{&JlqDgv1z7XRW}`;so#(ZNO98@=P3cwQd%Cn#(5 zAfRVLKa~ed?tMnmzN6Y`osQ-)ZWKf-o^+Q4Q}^+`HrO=Q_Hmk)W+tkamBBXZoh!of zfVCg9T>HdhhKRvvVZ31KQ996XLy|`j64;Cc%YH`uZM5=|Nwi|r-*$_MI)Nk0VE4jE zyvM5@O>GvZSp8JiUDK6lZ_vU+Wy+G6Fg+3N}t)Nfm(>V0_7iq@qx%wDq7 zVBmbSxp%xok#hLrRQa^BO{|;FB%WD%B*o|VQwXa|y?A}JcEiwdz;R~vukf%lmc&H; zu>NroG2v0@NBBU)jqjHl-nQC(5b(hy+RmZ-{rQ zGu)L~n=3y4E%D=>>j!ql%=fj0yv>YbHj!@Ga^Fo$SXtPjPv&84wr3%dINRr3w>bRx zI$UvPQfLGy^t{f?bUN%;3)K1H_!9|&tfbB^+C6e35oQrCV!C0dVseDBsS@J^aABMV zJ)`xIe@tljzXS~zoh{a>P{`I8Se<%5n%mM#{7Ax{ppHf1)3j9gssp(*su#%R`DS~r zp1>07l^V50?JqZ>8$zh=IzsHXBcNA=&buUXEP1T$YnLUC-bpBkCOxwqYCSFaf~t*n z!*V^xNvnkT@774?7Dmx+7>A+88*KF4uX@qZ;G%0dPGow&t6pkHx4%GP{ChIK-H#!PurKQ;?uCdSIS|7X`C{kO*1+cuDa6r1Jfzi4*pL>4x=+L2(O9w?j_U1p zT$1mLpa(Dteho{453zo@_eLz7(~n15l~H703uhcS{kLjMdM#X%Q0dC~$zny=ITH37fcrgj2|U#d z>xy!dE@MlLKegkp&o|{M!1`N)mI}eh@P?SAq<9(jlkfWcy?2!b4djX%_j);5FNIG} zvi#&L5PZ+lO%W;-Bi2Zyv!bT_9E;c9U^qi~$D1fj%A<+Q<->hNte3ny;(DqodZfpq zVI9mx7(Y_DgZvL3dOgGPTQ4AD0th))@gJbuv-QTfpb}-lNF}W5b(j21)lr^yN=Bo? ziaT?jefye^JdzSL%Q1k4CW?#^7$BPtoo?~Y5rc`i4yN0g_Nhj_meI9!QqP*ieyPFL z)W24|<@GLcRsW)bU~kE|SwE-4{InUx!Vy7EMeos0Xy!$R%eQFR7lMfHTp_rF`Xw&x z723utH25Br-24V}3)TS$s3>3K$JJLWuE9m(6$N~)GslgIL=GhSTI|ijhsw*n>f)(D8CSR@aAz}xc01Fm!ePOda*fvq5sKhZCb)cM{c zu|U5VkH5!4qxx^ey4;+dgRCTWB|k-|vqg+s&DWN)Av&Y7uf2edA7yHWX-kzgg zbPp@KNS+|gMYxVjcqmLUIIZBcSoI(X&z*5 zCbcy`s6aYn5$mEM*J}9c*22F^+3^Q=Ku&ta<$`0@M|{`;y9m=AH}B-&7S6|WS=HF4 z#b+$p#Q(2MQsid+&97HRj7OS-_QM~G5*CA)GR%tkj;-vk9W03dwYJQC1= zT@XQ@byvaZ)Hi`w@J%~_aDuD-nQ;=jfa{}(G*{ShUW={6RNTebl6#U{8iw#8xD%i_ zhGWo(zCUbAHERQzyUuY(BP0J1#K?1ELFQ|I53{c00r?dZ(Zn(HriHux1%DxMW#zhlD&Xz~_a#g9Q zTr=zwvbY(2A5>3FDpDo6TGm5>Tdkm0`C2Mg;BMfrYkzGbUTi$!`l)HefdA)svoC4= zk>MB+XN76SHwg0h<18!RNfnR=;7opTs<53Hgn8oHGKqXuIAZq>v|wLgXCY#a~x$in%>XVlC$|vZ+pPLcdc! zxZPm80iETB&-3&c@$LsXn|HsjG`8v?B~eJYh*U@RtcH|9{dsbd-%BzE)>2v9F2K=2 zc$L_9hg#Bg+9Qse0=o4>J)nxs=IPVFXn@hYNQw#lkki57TnLQ1p6apI$%js6sJt_bYoT_ z=bQ_R=H8&4cr20V&zq=Ub)yr+>dEYVf}KZqI82+aM0W&_e$m53FeF%8_yYq;tx;K$ zAVG!b4Brc`vWDwXhxe56ZtI~n;nj+pZN|p@t8JRGa4AP*LL(m+x;o-Vt5Y)Ui(VZf z<_ba)WqX9*N(U5(^LEIPZB%M_#snp}$(owtc+MAU-8LJmo^r4C$TLZt4~-qC%FcRL z*?y03|Ng1-iFlp7z|W7xqs_XA(IXPrum9`l%!`qCc8BCxE600wuOBu0oz&FeBxx#9 zGGGZ@6rbPf&dW^Fs803D#%Yj5R1Lxi(xUG}-LbH`O{jqkh=F!=U*QlCjW2S)@I|=1j4)VbuzLfxlw0zd>r!#B3VdwjWo# zFog07CZj#lGPw_u4}NYC>l_SHYB?^pR{-E&!_#L`ydU0GwXU(=H5zjJyeBU8sZ;~C zHF?-qF=o-AypxYz@6`BiFjCuOtb!75sml`)>|Gu(T92q%Od`UitJ1l&Elmbo2uRXT z1+DpXYX>w!DOZ~3BNjK7OIv6LFB08H1!S$&8S#oRZB1s4eI4^|!=+;!eiM=qdLa@gwl1AazBxR$A7{h=7zMrT{W5~dn<_tP zTY{C&13Yn9ue>ZaT(l6+Qj}o9HQ4Ob4;1loput`mQk5C#QU970XuF{MXJL}HdhGL+ zcP1+(=n2XKP9yf^7lDIh&Sk0OowhD;dFj_U;hK}MClJ!8ZTA#91sD{ZJh?j$7gW*D z_4(5Inw9DGQKftJ#au-8<-ZDp35CeaB#7P7;dRa9@*g~d;vv~l--`uE2FzNpxYWi- z;yG6k5g&PjnOJmhxB~jo=t4fRAh8d8^m|SCa8|7US8o9jUoWM3P!T%KT`{m_^N2_2 z7M$K+&!AhxJVlzpSpE_s4&_*V&(!|;049F3$MHusGERT`?^9p6un9$hdd6U{_1HoZ zL;4H}xYs+bku1UWk@@?BblwYLc<5k#P!IS8_*+y6*31$Vjyt-Kk~S z|I^MK=zR6(R?_HbTwa0d*XZ_X8&&wGipIU|uBD9W7lTG+bx3Zsb5^vkS;lFJYLed? zYgeCa#HS10EEmQxB#^3f4N_^T$1qw>V_>&!{4(zHSEB>9nt!LPSf&EWYzi0rxp|Tw zcO;#X&#P$E9XPgt*rpXiSR^(lwui+=l(Q0&NUL zx}SwK1IafJ@}5iVTw-5L12%^O+WvD~G^rVvchqQVh*83*6J%DI>rP%dc55u15q-u3 z6)vPxEM**0w69>v*TR#7C+23L@BCO0xLN3wLW`|#N^G*4Xr5=8qPabHVTr4Z;`yOF+-W zqSu3F@i@#Sw-!D|s&J@`-4gRi3G@-kj;Ku<5cAu8ES6KhfgQ%ep~ZtkOdPvB+gk|V zSjece>B?*bjC3%UtHAGpye2Fd;E=N$W{DJ*>u_I9L^iU^rG0&4>VE!19w3eb=WCJd z2B#T*sANYMqJk-0S2UPNbofaXLV#-BcEz^cgjJWy!5TOG&H6{oYyHh!E2BB}1Q`%j z|9S8hp;-oYxyq1L6=KW>2P$OzBfA0oT!LFYGbiD^!Sc@v3j`%nEivxnY9ZyQ{HzDH zAwe1|72>2O4DgP*(XCvK(N8W9E!8t`F#mdiG`+ISe@5&mG@g21@N{9-4?3G@TN)u@ zz`H^bU}`L>I}Pv>j6`}zLKB{VDA~inGmI1YgtvdORTCbGieJO!fHjxn4l5dRZ;{NR zT+7rI!STq&dN(Mzk-^vyYm(B?^2-2x!)B|N)cea9^43jg|FpO?%!*)=K>bbcEkh;D zhplC2&0jw1TQeiB1w57*5+})gKmEW#}-IKu_q(YkrSkCR2;(()2BBpDFUFyY+B!{|X z&3f>{qQMsfqG;1-hSLcCaC98)*2OrGtwtDp7oPKbg~0L| zj#ds(xTeep^vV`hO2i^HYs{D}@jiFb$FEsQ-MTVNa#B03*ek=Gr{dE{aJh`&6k#m0 z!T@8LZ-s6m{?0&}R~Tw5fF|;6hpnaY#$xu&*E@VqmN&G-3Cjn?;|~DsubteT%c;r0 z-t(ek7uEgDML#J9X$#=)HvZhEL`K@3!%tAi(ep~K>9P6v%3}DQo{wrAilB=(EJ=_& zZMVhnQoFIv)SP(Fe!=OjRopTcr-X=nw?ouT2V)4f`c1incY5z5;sfs(6EdC7Li?6vih;TUED=Ny$4%rOEoC@yrjb-O}t@ z;&{Z;uQulvvmmgCKNlcbIJ;7mi~ zrjTeETnp@N85zv$uSr2MYVYXmn9B#`4tMPtrM$Qn)*J_3g$)WppRkV^3=lz|%$SkE zpvt8rG^|geCmO$I2o1{y*VPLNp{xmCP-30AVF>mPN6R!~ums{3n*VoVIy zHkG#gu7I58`i@YTyaq-HsR)*#iNj_$=aS-@O#A19DeQ`U_8S@R6L|!@PnBj9e4W#+}EFQQ}PceDO47up_s8aD6CvsK?3GxJk z+`#501+R2uRk&8DooSS_=TB8*ueGpZk{Wa+bAm@&(LfeOI!_JO`xi-B`W$N4f&0vP zn$KGn-L{Q|u(IoVPn@?efRgJ@JW8A&Ua4gENlNre;sC!gYexhymDU{}0t#29W;24S zJ|8w%RWBN9l$JJ+|0>#fl+h9{3uP)OLRQWKTCheMqNm zdML)g@{8_e&o_lpkpvi_YaJf=_nW8k<8@UH=XrDieXJoxOhLR}Z}$H4se6&0nP9Da z$)98G&?i&O7^}g$@aUD+!~npTHbM6iyl0Md`e*fO%m;3HuEOIrjl$=*6>yA~KW2gw zbrICv0LvXcU~W}2$5i+>xW;E+^A5m2)=CGO$AN|csqwOPK&hV8Vw~!JfhzGDfI{IQ z;Q%D(-WrIbN`Nfe@7NV!u`JSZXxq9@(6>8%*Q5m?iHgKq0Kel6z=VD5^O3{-F4%Tk zJkwE}cP13bem*8(at1I#=*C{%hFTx*L;=KJdL}e`Y`6W!uFn9pL6C`fAdN4mmG8As z53{3^I;V=ReWes^?A!J7r@VWKeRO-d74JggnOD2pm0siV-6 zwdJY^%b|h{mZd zXb}M!gHhx){K$(SbI(u>#?kT@zIli$;rtQcCzh-`pS4#Eem%I}HJI7YzVkL-1zzEv z5N)@a@n2(&@i8}DLK8qAOZN|VZ(QkEITuJ=4>O%sQJe7uGC9O8wgE}HViw$n2k=<- z4~v!vQYN&6Uy%?i+KdvN>RRX4lCRX&TEh3jBe%VvM83MxVRnWFGmFy0Gi}%d-5(`w zJ*!l18F_t~ZrQzFY<0{kbSX$b&$~&?ycfo0?m^e{(=gyT*}`xk6s~L*5&9d1uykY1 z8Yb}1o zBnRB!Q;eh}Th@S>+3D!7xaAsPadw-q2Gsq^FO1N(J1czMiS{0O6GBlh7Y)d0DWK7I zKPD6bIuOYpy4!k$qb5OC9VEAZL$P23C~@9PBT{2Q;#-3%q7>ZX=T}18bg`f4x!cWb zZ0Lt%YES?0M?)ZAzR*H#g!)b$oJmf7J8&Ur#sWbn4c+kQ7nugHFMAqo|WJiW5>FyE|BxPF0QukryG<9$e=9& zOaSZqKVUSl%6HT)Myu0v34l>FBK`tg6WXFY__X%eGn6O?QrzDF%u`Osd|v&co$(KG zTtNYP#RP@qCph_>{ntUR^QzD8xRehw~g?2Fg7){e-d>CPEkSu5@8EuNyxMKcs0G6MlO@KPoU3=mj zcU%VMC69~es7wu~Im|!#pL?6{9d%GG=Nttb^Q=5Q-rqwq>ilZdaX-lJ>VEt>#|19K z@!sHA=#BM=6ni-7U8rN5|0o70zSBHEN6i_wc(#>}s#F1pk!R5EF7w5mx;M z#q+wodxlBVRloDN`VMTWkAStoW?f0#pe5m0xzM^8SH3C?pnZ=JF<-n!)vK2EhQ9v; zI}TdPTe!b&E*WZNnbf?yWw;&&h}xVEWc0#y0ehM$_iYbpio7E-SYm&uRhtEQV<(u+ zr?{$~@grhx&v)!6aK5f`4HFQ*l2(k6hn^$045Zn&b@!wHQV%$wYnWvv-rRP2NK8$T z-9U(Z$VWn(PDF8bS1o~-568EOlJ?MQ9Do!~D+tq*DLnSzoKfB0C!e^UIt*XQy@G|> z8&G0-oMBr(Je+aj90<{@@S@U$=b?N6OVo*(4Dr)R_v}ulJ_3{+1wS8+O@WeI~WZKE~L-~Z#=}M>!&3=9n zaQ0Nm?Z&)V_WHY>8AbyOVnlbHade_e2T?1aRK|t$fHJ}e98r)5)$gQYap;z zR8m`8&ZQ5L+NWUSKs26QxiAR4l-*<((ZMVq;AmS-2Toc5Y*jZ+u|YfM`S#fP598tY zJTb!FbE%i?Ms0t3lW8PiNeG0I40(Q2`vor3`+{yGbjv4FiF(#_nJbq;%!(89`@vr=QHV`7xjDeC` zb0TT>Eo3tz^L%Ly-{z_3?N)Xo_N8ejgV4&hBGRpjEJQ!-2FAasE1LvLSovh35R(Dj zhFPOCoQdtuR#vOsxlrXWfHY{|{E3tmfxgKY@;T~y4j387+i*^Q;E%ReY8Q5MjQCfe zL9V|w_rio&I3H9>CVY-cQA|N!=oO*%wj_hQRnO)$3z>~if&Tu7MZEsV=_9^rrcOQtPbJ{wPJRT4 z4ZnK-k_8B8r36^#5fD$VDphjoLwxgO3g6*HJk>N1?}jjKgSa7*NCmcPK`Z6#=5VsX zfmnJ?1(-%&S6mj0gntzHBj1}opUZzGTi(%%$%Zn4X5Te}SO_`3c;q6&zlS-aXLBZb1-n=nRlWdKEs>~AF3imXj5eQ-5z?`+(4*&ZqIxKTJDRulu!?}V#&EK z)3%|KU&;y~i=;2#p%qyj&g@lS}3UBB6x@UQw^#ym+Jd>?)@&cUs;z_ zylFQoFz3~iN0hB8G!eFvO+bNBrT(e`NHdD)sE$l-4`V_-A8?&ZHc#aj_*e$Dr32$; ztqtTF6a{}oax;CNnOThyJ&9=^WoDKXIPH1Uff!|uTIzz=hfY0PD%%oyt=O&z`3l9x z(J%h38ZDj`aBSr_N+Jo`H`I?#dY5K(niATNLVQxnCP`k`_8sQxljjX#tN^Iv4VS?L`rom zH$Qz69L78o4fKj=_F-?19z$VwYAsOIpkbHzmM_kPxdAi>c1<-{)**~bize M}6j za!_Yw#5uB-vR{AA_bm` zyThrk0QKQoO~Ra!g~dMWYqO46NYhNEFt!U&FiLyt7KmEC`;87XK^HPt@1?zExx7wH z87GpjjHAR}xIZ_$Me+H4vFp5Qx(6J#iax!E49Bgr9LSl`y^QxKzTigySd0Aa+cz8Mq@*NXo;tH$;4XT!0p*d0VdV7%K)i_sO|nL! zeA@k0K>pj#&Q7?m^*{P8&KvDY{jiVwGnov^a))jSHBxJD7h=#_&N#EM!40NA;n|iN zX%do?Ljl5VFAau4-_pbFxfo&&6c0uD`RUOWFf{3h-@qEUEC#yS_4M?B<`=`SN&|sB zM;u&SKGkbr<5?X>9;09&>rqUZd#+di!P{>ZG6p;o(4O6p`&OY`jGBpwb1q%syfHh4 zEf_Lh+)?(Po{OHGS+Bhjz#h>E!&95SFhej%w)NV7u|ClC3C@w~*glV#JZX#+@X>hJ z*IQ4>bB<;Uy+_}BLE|@)8iHY{sHj;t&&$UFrCYNSrcQjBjj1+;ld#5@ z%w9eK54zW+fKY0tLO~|0wc>)xozs%aB9`7!D0oLhpvt%kH3MbyS zCbAo^R>XRobnG`Xb*)adv3@N(xZ@|~2*t-g>KOvgyeHn+guxU5nK zYC}s?a5_l#DSI0={rG-}CjO7`tCy!Q-G+8{(B!%ye{SjRvVyoR5P{cbujotd+8n5T zg|Zj6Ir!#F-~>`!u*YJP<9QZ?xsG(+OCz%(1qOS=YTQnEe|6ZK!t|cgv^$7> z-*#*QK-?X7e*cK5nBiBvY5Fp{p$$kt)_fLzs*M}BQp-k(i=2BB=gZ^%atiCzNc*Om zU={&DG|9$f7QhJ}p&{%{Q0Dvy{UGD0idJ4xDr4DR&lX`P^}`vn)chKgUkOP6lA-Ym@ja?>Cx z&jhdyZONo8s^R1p$e0;DF|>h$TlfC8l{K^do267PpAt}-H>gli&h4|R;2I*Ej;`o0 zAY`KF`Em7m4dCHj69;Cz{2yq7X~K?j)Q}&L$TvpQ6p8RpswMZE5}{cce-vV|<{1Nw zo{-_?M9K@Gp*`TQQ2+Pp#r5^R*G}2M_f@ykuhrG9vQ9bWk%0DqQ}c@~JdXZZoOdCH zG9BGD>VI!`uRJp1c9BZp|^R<#0lB0Rzn% zM`@GkUPJFUN9cp%3&e<#14vQ&@6V0G%FCI7f?Z6%tO-?Ytd_8N?5~R^ZBhdF-7W03 zPFjiTQiCn7xrIfeYf@3++$_+A0In03K*wk8&U?CG_%kz;W$j;az-~27>4*%h*0g=U zMJcK%LWKPbH-$%PG=F#=!vF83a>$7Ewt?NNf}UQcw{~zHN=j-_0~2uLQwi&)t1OG= z*^Ed%09ydzJm~oUZ-v?OU@jOy)8f3$aT7^dlFu4VuZqWB9-b_73LT?}My3qCV%7On zi83(9U|bw761-ey@t1HQzs!g!)Inb(*h zp2!$Gd!7FGyl^iGJT$^tr5yj==H3ki0{I(G;?xZcF?&9PLau7{CXC|c{4>hLSPWG@ zWj%?FK0f;y(}$Z=LN0T}|2|L9UYVlc)k35FDS$@D2U^%^(_UjeF);EldqmG#;TH6hNaGD1%qIa3MQ;){x>vbY0sAQfrXjC z*b5F=--Oaw_10PP^kmN^QkTC~kkXpxPf?N~4ZC(CRZ%1|ZeW1NUZyDee5Tz0#+_m@ z<+`AR1O++)dmn&q{tV1Vc$k>t_I|@<+*mC4^>xe%ks-{X9<(^A%S8wJ8RN^t$qX9+ zu281hxI^-PW6M{=z#ztPvFYUubP&ieDvm>=>F@TVtlE)-9cf>o>WYa_10MkyCQ}ic znClJ^Lv-ma6j!CY>*Hx3NtX5b>1Rq-Xm5-_1tv-xp1P zO1K3y$x|v<>N7OeR>qo|5MZ%vyxbiUwWT??Y|D7c+^RlM_Va7!HyOMUx;T#Ns)u5) zM?G{Nt#(lWYhuy%uUnvEQq$EXw5ipwnqav{H!K=X0EK-Ln*tAOUxn1+j`DxyuNPkNCZx& z#&>sfQ&U$De)ol+54C;li-7&&zvUmzS32Yxvb?ailF0mqiP6zMfF#xs{UG9bAZcYq zcXzoTVb&XNyPx0)>m3KCCv{EDVzGzf(ozdxlr1z_8ZEbd{QY(Rp1nuwO6RJ`dLnn> zswD0pKBFPgf40A_A$=k-F|nYsx}xIkq5zS$Dswr^(@G*KIl1wX0*ITq^4{V(SZaNL zAAmUjDXI!s#^aj~$;EtZ7Uw#Ao13bDGZLHCFBLK~e0F~rD=QrgKK}$ti-h#_(y?U! zG=C08#$Q)Tod{qcg8&%OcE7j$_4TuwUfa^#C#Iwn`{(}oqv=S2f<<1@k-k-;QQ^0G zc3WIYs&Km!jzLuDk9BqjEPo5vxnI6~uQa)O*U51!ZuO&%{Z_>?ixg$P)4`yVLrA9& z(UxKVPkd-Y;soP4(*Y`#WAM_a&6PT@Q}fXr5dxEd+Y(QX(+wm1Vw5_``A;r*aLHYb zlwizb=Hj9$0``e>CeEC}v%g+IjbIZ-ut}AIz20-+JslRdv?RB*Ypw&$9K|)GgMa%L zn)Eh30%2K(i5}i+B3CTyCUM{K_H1jx9;`{7FMAVtlj0boh8Ik?{$ak(O1CSZqsa)Y zGiCe)Ym>tmwx6$J+|Plh4k~#sB`mXfpKj|Wy7lq;XqoSnbtlUsB+>>r3odIi-h(8ZOExh$ zZuuqL;nz8$hAwsb|L|ld^E>(30{9#nFPr(!yf0Bc%qtjej_}@&`ZNURD^Tr{u|n>l z9vGVf?}YJzN~$ty3+PD6?Qb@CV(@sZgrjm)ofQGqqcPGUK}JcFaja#3yk1l!|B- zx9ZoJ8lX&|08Dbo?{5B?>r_#JDW~kKVn~ga2xSt+dQuY697mY@`RGQbVxUmQ|Rzj_x=@z8Y675Zd!J7f} zvvr2eZgI+k$sRUJC?OTf@ua^Nhn++6efKUu)9E!oOjkQTb{y3bNO4qeWu^Obq4{hy zI_JtOTFZ4A_sLSe?4|%{nLvYzX-DWRGIa(4%YAblR?2jc2P3dC8!S+Rp-CExA~nLs8#H}xu~qG5zJ<&h(ir&swBT`CH{4qX zGCggJ{*{X2?7fQ*W;yQfWx;}RzY}%vnX4wpVZrL4_PGSk&ZK}twaaWnXUMCor%yM4#pA{p?(D4Q~#rDH%4ruT)U|2qQ0ZkdNWh0 zkT}#i6fo4OWF7p#uOzbfC*k5%N2p{qDrJ`$aFFn|)OvR{w0)L_V6)N52lLgusyCbC zru+UOl0|?7RcC^`a+k!25JS#5w_%EAZ`%3CpCL#$Kqy~>4TD%o|55oG%M5>PB?PK ze#&RF;OnHL2H{V$tR2p`zqMjp<0w`4&S>dSB#5f0E-IRU&d+o+!C?TK>a}_}zd7d7 zWq;dP3kUEM)Od7thh>;uP}xZ?22q>IgKnEWUffQKi+@?(fy)1WYGj$xV_r+9#$QD9 z&d(M1Z=+Wf;pv>Bx=3(;{Pag>sGNOsYlXGTw@oo|RkKxL2DG2O#$5i zflCzxuHk-yVD_#r)C+Q~BMp;93ii2@U_t6XCFkl*3{+3RRJWWuE~iA6xOcW#S&Fo4 z%jClx9qHp;?Ym;tdGIB-ih4+VkBq#{G~MdbJaGHO@Ah?UqDZmhFMF!p!8hYVd)QO^ zA{B2i>~h1*Q#!)gSpd(M8?}YZXpGq^1q)3U%^yaH^>Qi6NEQu3b?a0V@y2)t1 zcZoauOo!tw$&PU+#u&9%hp&HKRRB!>$Kt=dZ!3>Nn>-GmRF$>pm0C0|zc>4Ky;<5% zbv$r8mTB_sl%3UVdp^=^n(nB+J#xH^7)ho&9X|U)xbak##>^sHFPR3)={!2zZmo>J z=ecwX-0nC!E>8FLr3?4p+cr-B{g_#db|8FhO?32Rh;-zCw6j7mKcR8$HdUJdr=t*x zJ0>kbK8BU;Qa$MPko=4F+=QH*%Em! z>$U09-qhVzzIB)#ig_N8A%4q6pO*F|9ZR8B3RIszLE;ZzJDuAGjV8XNTlHJ!d6Wio zH4ccDOVV0YZ8~>Oz;;qzTi>o+*dU6fDji+=)JlK*NtFn3TiO&<9z)#gPE)}JPx`7K)DbI?;on-jKJ+5d_|434TVXbSY{!;08B@Y2Va-6518B)~J72uifhZ zboAvAnyhGm$=W3GE}&N4AjVJ41X5auO}f13l9?RT9FxmV%|9Gd?mwn3Zb~O}c!k#S z9c{^O# z-V@3GQ~PxIaaaRJNAk~E(c9duo5-?ph4WT=GKi0s9(diYLiX)oYw2(;DSUc<`fIRI z9x~IHSF^X2JHgqX?u`~dJ;+q5+%FTvZvY+Xs*h<+shkNae5Y=(V{+dl31?O%HFn{%xeXtI<5n@M$@|Bcu(WWuW;bwqcMKG1w z?U^yOtkd~!C;6iiL&!lM``MOHqP+rztEBk%rNynr{Az`TAvbQckVvy{vs9~L2VV|C zA;>AVZWHPLlQHjM{>Dd#K0BV+Ytz9A_WA)u#R%_(Uzfbsl0DOJ5mvtr_IPtcqasXl zCdn^1FR>iRhWlj;#YA+X>vqh!fh79>n7YbFUpd|u{4pFloJJh!8Z{flGeBKQSe5NoCuF`eF-8!zTJZLgDmNLP{0U`@GdA-ppO~o09z%P2n^tCsOSw zlc}`LI>rR+!kZ^PR4-+3 zKhxG9lC4nYXr4@Z5H+m0Gx(|F40}u^7Rhv#>LgCc<8(Qo&h8%G*b+X~3rnJU+6HM6 zR=fi$Af~#J#doJXa_HRjY1Nj0mBRUo^-juE)aSRaiVL5P;UZTX7USO8D-yvy2sov7 zB<$e^AgEs+&l6jx_}*>=nBdmhZc$NjDK;l+Gx<=SUX8%s(Q#?Oe@n<>J)9|?6v?4z z(!^=4C|Y6%Y3{ctxI0u%BQ`r>YB1-Gsfp+fE?akr(ut_^xjrl(mN+rx-S{7(&aaOY7Qm1m2f07UeT9K}TV6}QRacX?W)vG@q^)BL8yB(Clxt~cEpR`U1=$uApd26<~ zK=eATbZ<_MkzAPQP#?}4Nm?1sJxRuijn@zs6R)Il_4oPk15D5b#+pltPo6N=nNnY! z<5R@E!aMN}wLkTZd8qc{JbTW|sJAF10%rxys%O><#a78UFj>-%+YX&YIgZXwGJoAU z9WF?FCA3bAsdl4V-#XZ=GZehkNLeu$?&R?xGDCUeQ$Jc8|7w%07W=6w=1}y+oGkWA z3uBeq6SKs#gveXGf#gw%G!@UiF50V+Eq1yLXBY2DGKtMj#3&X!D{f6GZ!?@-3IJfP)uJYIHFTlV(gH0DVq=RT(B|DK6LZv9OPks zkNwjM=~FSdJ|5;D%%zGdiZMQy)}ht)o9J!vX{(!S_aUA5r>!gCMp^BhV3F++T>QVp!PgeTjMd(NI-Ew-yf(>M`^gi& z8^bozUu~eCoJ+gkFc$x}+oyu1$;+kHGM5klwurX8)*oO@xwF{Da))63s){r}e7f+Cd+Uh2bU~vv$AxNR0bK-C`fVh=0P; zJ28VnZy^|;Ku=HarNw9|lKS4h@9o^6&L!*Z7UlgFlM2rVvTO0S-TFLKhgw1e^&r1s z7xYIDe%O7Oxx?phniF#tv+DugF`ZhGe6Ff}*}k(_W3$I2hoKx}t;jeh#6eIu}P)M@du(U=+!z($D1cF{`Kwl8)%Ert>Tc>%g*#Y%I zHYp>3D8vBFZ2N<1n)QkdzkvkoMM9%No~F&ur#VKaCyf%bbv@AFG+L7stVgp$S}Kkv zBM<|p*N-}Z_*JS}9=%=}MzkaKN<^Jif#@KoF8JuXz(}s1btSa>*DJzeQAg(u5%%4y z0e1Ib^eDe20!klQB5tQsza?(h`c)Zxcd1X#OnII`R~`Hg0()oe%*Be>#YhHI!B*$oc53t9fv9)<2vzh!f5(_~dR z90+}uELuEYCchc((%LTfaL-5!XV9bCLsO!(go&^jf7yDgBRVVG!8h)~3?cdA*clz~ zcx6=OhKJJ6D6Vl?>ZT=_n!&l04sn>~6X?X+G)uGY@M0@X`(&k6xpP;>+4otx^ZKgh z{w7{^lSh6f zqubRPYlJbXB(sOSHYQ*1FK|jtn#>0-5%ltqlbe8(n~nWx$FI4PdN{-GX4oUhC!ovM zgdX{Xq&XLkL^_5GT75+-FIemJZ-_f19tC75Vsk2S>xAZgg{8h25PjDR7IB37cvr}a zR)BQu1VuMEn_d6s3qkVfegl^t&YVX%FM7F0fR{HPH~+befAz{dLr&eS;bq65$EBwS zL2`E2CHn`F1!M%%3Gg_7IP1vX7f?{gc1S|gUJd?Z6egshDd zh6Pn~D+UH-=Fsxe>9zz-^8}g4_71h7vIh&kw;8#nUMZR`Y^c6Sur*q4vf*1m{6BZT7HL%`C6C5sIzt?#qE3e9lU!q6? zFBj`an(ACcn?0)rQ%vMTNu-P3PUZrV!u);Cp)h}A2M9*&nX;q$>0WC%gd!}LYSVi0 zJ{b)7M@N&kD)hE7BvWEYN=QcMr`nODivx#qjuJa!R3{bwchd zcf3zZ*}wvOrNN)vOh^#TT{7p^NT4RN?z}o&(Plxf*dXL=(93bC+=A;jEp%v2ygM)Z zus#9oQlY`g3_WHU)bx_K&29eCeL_BtxqF*0Ym7-090V;d&z`a=oXG1Ep|sLTHQ|Pb z62vX$OaLhBB)w-()rF59$G zz>!jH05C8GcNbzKaoR^K{VaE#PiKD)(lpQfg546vOwfB8mrp@S@ZMIk=+)vU?qp@+ z`JsrSO}!o?whf-C=X#|>n(%7D6#h=S6c`c~%Ix9~vOt6_=U<8G4PhXw?X0=ZJzt3J zxbgpi<>5%tyEN)(kHgHICB(%)5_=x8m;!h*+ftEU^TLnR)Z?jIWOYdkR0vf%CH4)1 zr{`>v7%qJ10JCO~=P3{ucT{7-A#xG>KC&Pn@@G|09^}7*Y$y)Q5eQ|lFZG3v7cbDM z5|GYeHhWx&)B#0h0hS4A;H*d?wkoA|U3wGXGbTcS&jy~Ck~FHSSieun&!;8;_zo@A zW4lVPI|o44*T-#MUZDWM={b|4>$1QCMo0Q}87TyM!qJj`_yFs;GbCIWV`Kmbs|lo~ zr7u5ixM15l()`1E01v|n2VQ6ca(Tv}&h;jswQlOw)zyeyCBQA40vK#LbVK#z zfC?v-QYsrq0NvMysFS;Q+BtGafFT)QiB>}hf(dlA7!M?! z%|%No;WD46d(tJVg(~>d)|VFhSj;z`a+=7H?FLW%^FI#<@G1F{i?;)9>NT8BR|wa0 zGBcq{Tc3FV4%pyllkmK!o%=t;1LPxJB%6j@J2{Txuxa@nwxo6eh&weRB4Wg@!e*Jr zG+n?uoOEFW)Ph+e0yIJXXGx_R$zMB%RuD2{zG(!yAf*oAA0d5Eb~*y|>ytG>ChL#L zNUF{MFp9t*TuV5lyg;k#l~d`(#l@up&3QxEmb?JqZ%2ATIq67eY!NcqkfAC3qL+56 znN_NY*i6D50myg6jtpD{VMQG&kM9OB07ffkuzkY-@^FYsSEXl8#q&Lokz8#X)}jMdIyu(`4EQ-S|VMWcBb1Okmfv<3uO3@bZ2 z|Cv|7RQy#+d|tn`y?|8h)2_8~4h-w*k=O-<{A=M65gegA??H**x>f$2TQM}{PY*K{;0$!IQCH62g-?t_9IsZN%9ZdRpewNu^1{F{{*MkPJ zP3x$ssqNB$x*R)b$HN0}|C-<5=_R3{xW{33OCdxFx&T;JXEjyTkDbB*VRr$jET(F{ zn~c-fPqX?|{fDCj3=77-tfHFP%?AKHHy;7;xr$&*k^Jx{uWJb#C1v-KwU3Y{`~R$k z44bi?wo}mjwOWrdP>MTrmQf8bZY=>~b#E*30zpETh0dl3K3)1eQqN3t~^t%nrjji!FYXvsxh`&Efwpoel zwWZx2&A&^C-lt^e?wNw%rwi25A8Gcy;Sr4p-U03iA0Ms`O^G}XkU_uy-zw6BN;@d^ zI7m|x5`JMFBS;FD5%RidM9e;hRuKK~F{FOV7A;LYr1~D9W384((=b3BI}ia7-%iuc zwB5G)Uy%Z2#nF2eL16}H74`M?BetzioLeh99UUUOnx?5BqEgMCuxHAo+5eix>rYD8 zWfeTQ{uco_dVBN?49Y7&m zT^K1bQlqOcphg3<%H>8^SIBykB98-t9tS=9Zmb<61LfuiH%0b;XC_3^gXRGv5Y3uq z&Ux8+_M?on^v_JA$zO8Gu)MUi1N6zIuwmc+{nQWxd1W=2@3rpNNAn{9KjuHQNN>zB z`h%_a$Xwu6VqQwte>YNBY~~RqZqu-G)nNqJ3fvE~kT``2bX>gpgY9^64<1~kjXH5C^A#)dgH zHN_2({7R-qMp>oh$(q6`|M>%{F0z%CQbV+=4J;p^36@CgEPd7;&`qJ1jfSS5KG|21 zlL+&#+z7IyWVrowKC+s~OMYsBL9rXU0C{OwgWYeQK(N2Gq(e8(2lM})O~M5EekB#t z4s}Tdnx>6R7pm7TEEahtH@cqMU=PcHk>CDzm$Y}$JP6kH$lG94Z}vnuGU_#PQ;;qI zERt&^&;fuxdA1!ZP3~V47o%rYJO4CL(?Md<=zO^2wGCFUI+!g60RhPfq#-Te(Uc9S zvi*x}Ksd)j=n*r&iiw~U~Dhh-;o5MCvr7{aL z!ns}`)ss7AaGjPWG+c=6R#UV5yzO!+M<5DeD3Ef52Z(n3Fq+KZArd7(xElfxd~XIU zixsff9|J1{X&2uBZ%Z+x$o)xc*MCeKus6Hw~ORR|ik?N1c~`5+m$!@&f)Fc+p(12ZNO&!~!Y@Y7Zr(;yD* z;s$`Uu8d;TPJfTC5gl0!13&3$76{lM&6U>yM;Wu_48547WHx0y7`zUoY;*&PzF=UB zZWi4QJR_*vu>G^hIpAPBtZ#G*C;fII#^`N{)DK}5lJU*Itl)Ks4AIN0Z3^vE+`Lm9 zI2ZfhkI|2Se8p74%vKN+xwM~4l&-OL(f}O#Z9C=VXCW!K=tJqyZ^!=YUc-HTb}i5M zha(LQJf<@9HP$H!_^AmACN0=G@AmC(YW{ONF^Cc6H`1j*C4M+M9ne$0POY%E3y_!e z!$nC9>D3f-Cek6QuO3)Yafzvb%2*@G6z0i^{9J<LhFNWa#It>T`9F<)Iq)25XK%Ya$Vb}}~BS|cs z8XvV~c^Y!i=3xGHU>IobW+O@oh4k9<+@PqAZSfPh4Gv{F9^4$MdFX*azYYIeNuENA zy!mX=gR)K($CIV{$$90S(ezUSKDV;FrFgi|5AE^L|Ge`f8JSH|1@9VdG$mO*Qizeh9TDtFHc7RBQbJ^QVYBndY0*IM?$41cM zf2XmTMmnx{1dId*zBMg7T5g7#u~-w zD~xc`j3Vk*v&F6tsMto%&mBx<=Bh0dFXoJ+re~l>N8X3Haletp15R2DQs&D@va zkSRP=TE11mB8plig`8!5RVu@|CjX2U*$%Mqf2 zr!r3VnarXBI1Xo3DS0VT327A8&mQ@+c=;s^y$z{hWgNEPnrkTj9+D5)OxKuJ5=xpx z7KfIKs@j1A$*d~V@#F%W=*tri2D9IgHR`u538?1-?gO=^e!E1BNL0P^kiX;ug@KE| zS~l%#MUMo#dFTFF0Wl`C@d}Wkv3`Q%Ng0T$6 z7^L~68LaeL%Y6{7_zAfcx~9Bb_}w%}wVRrLIgDcw$KYZGD|wCacb|Gzqt=7An&#L{ zR)fg=%|M#!b#Vo>UBE?bq(W20A$a*0{ipP#=;*J2EU2^&$m2tQ_wKs^&{wb%s2!da zveP3Gb)nK@CV*H%It9FJbnv&1A7~TU6dl`g0z{1Ed_?GIet7tCUyG)Qa2G5wBv6w= zd_Iy#qos#ZfR-m8EYh~}^CMZe%0I(B5ya0;?UkLGd5zobcr&EG>mITg&trWG0cUgbNcuN zSPFJrKUs2|y5q(e`mZRt0B3|`Tx7uI`_$qic-%lg=}({9f$Fyf@VhxV6pM6mV@I$= zZm)neAQDj6YWD@Cd^`AvDUN ztqmqWqmULiIipu55$D`6Plz_hn{5mdU=a`?0M`yxTtMp@qz z>-jSwY5H47(IO7bmzgoe(rvL*x`n`Qe1YzTV?m?A6|A|>Wi(Uu6Uux?#votSnztoo zHi6p`*ksAJesp>Dzb9qHE`X**fVTWBN=m+lOC&z$4WyU57J3=K=QXZrKa2h=_44xc zzmvrcnXDPIR`TZf<&vYAB*Y$!xGLU*&E^4rzw2CevPy~PZpnxHixCIW5}CVUsZ(( z=#8rqV0D$1jeb)0-m8LK+p$90A|bIUI%)tLX-=*bhZWx7jY=Jiqo6-}zhoNA!52_o zhI%b2;7ueQym+#B&21bgHdI~)Xv3Iac5BaeYEg}5zg;aQr z#WU3uDK8D|v}gV~BIf^XZjYNXI>>0~t0*(*mIaq<&#pLHT^s36?2+84UI%`Uc-H4D zQ(|i<$D*$gNRCD;#4V#Wun^nr9VR(J~-XVnBGX`ZdkiZlhh@ zU?KP&J5%KreOzB|W;xMAXw7EvDN)BPot~sQh*S&D-I5@|>_-JBVR%CrS@|r+$8%GV z=v4?t8pGYttd3)Z+9zH#R?bSySDtsizucI@Dm}5B*Z6-`b{47Ic@u0wLSR3g*fnb zu51>I+*(XmwD?@8HPBS>j{ICkYx~Pm-jO@##jceqQ`EmgrTRIn;uq`uj~_qWfQ&*G z&uc4dH!j~JKm-X~#RQ3bAMG#Zh9<_(ax1jkmLSJ%>MO_upx?>u{W{_rD6wxvnJ?+66i zCMg!@8^)pWM0%@GiTTn1Xi)yNL8HQ4vfD1zDIsn?1KnV%%9D}%qK%aeWO-KR<{=Qw zXFzrgHy#tTI|*KfSC7eveiFFsBltRLqWArWvCp@kmn{VP^@z&q`rom%TY45(Ul8dy zeFGNmu>tCl2o zLRZFMgAVkL9Z@hghIZMuZEFI(bbkm-7YB}Vt*@A94{Cs{toZds`gdWTK1MYcE+lkH zdwctZKT1GVf~f0-P#{um0wUJi$@FJ`;7*xjI>>T|TQX)vlQ*1Y12IJ`uTaVyOY&AI z=y?9@Be<&A{CwQ-6G6gW*=I1Pm&(nhKyXMTG^q(im8kb5_fdvz0=Z@+4m3(5H|tsxJ&HR;caXq{l`&=7vh{!@otuEsPH-!?Bp1l zk~F}41)RC^2!I#TeHQ{If>Jlka0G+0vBV^MjqFZfemdVqB(dD9SRwIJuoK&}DfMqiL7qZG!Db0Yz8mH?4LjY9UI2@}4k*;FrLv>fbFrE9 z!huXAOh6JZZfKb4?u`-1U~DDBc(I#Nn-07K&R57ge9NELr)`v*XZBxPQ1~P@+oL03 zJ7T>TGf({Zku*~%u>9Ws7}m{wWqB^Pc4A;~AJLrJ=tK>q-(MgEQ_q}>mZVZ|^ZryW z)c4c&5zq?!)!EtblPLhd)dAT9fYMtbqhX=qYl_K_|Hs|Kq#5iDJv2gygf1S+N);Ey$KkRnsJqQXoDF@7P=DN!YW1Qd{2B1}qa-%muqQ)CQG775}(CW_$(r?2` zenOsOfml}<5UNP+ikF<0+qox8WP)=jObljjEA0=$Eyrsg>`-XLJ0d6NgBd*4H`ZNC zIu-~8Y2OgUzg>Y+4=}~U{w;2-@BBKj^Xg9W;2q${{{Ya%M$^SeCs5=AsEQ?Mw9@46 z23*D2Z7bizay>)otZu6*G6RR(eim>uo%o2Z>KR;-2)>e_i*5qp$sff3n9Y!s@CE*L z0rN}%2Yfo&G^#9QrLb;dEk&0SyyvMmpB{fKK6@@8^LW(?enL3$^fob}I%&Sq`(kRk z2~;cZ0m@Q*i;cz5AH<>4&NvbWodOg3*M>E3VSq0carhAxC_^nPj3`STZB4VJ6Ehg+6SnU z(7OeW)RaPG230Ms118tUS32u+v7I_7z;gPV{rQv>Jt7)fu}aqn&rp=WfK~nhDLFuY z@P!X(6Xocx zW#OauuXR)%wJDM}jWFzYSo<82k}DW8WS_=?N%zqERX^VqgSwNov(lD?bGiat?vV)NzDOC7dghH2iJTc z1zLQ6Y_W*09ts1E)9-fkXEz&uxS!}0-zEl!ZHeu$#*KtvqG*@x@IUT; z$G6Y;5|k=#0p>?gU$K1y{1i<@c5G8tYKxpuN161-5L8PiBN;7)>vDROS$9{o%WQl} z6C5T7Lz;?3LomZ-3PXh|_#WTo$=`3H`5ShOXQqxZr5&>N^glT&&_Dny#z~e;8L!e~ z%nw)cxRU|=xXu1EWBbd~hCR|gKRgmUsV)?rFCRH2?7N_$_L0Y{IqkZSV`L73@xdtY zv)E@tUIvg)Vu!eiEwVS^CUl;fnyyt}b8c01ye{?a#>ahk=7w@)Vq=rO!GDhwQtB44 z8r6o*d-0n%8$b!LoGVZ@nERWXwggx_#*e-+mJigPL=0%d8qUR^^vdP~|&8xxiQSIpozT_+#0^dw@uTQd*#z>X` zKvyGdNkOY{Ov2A%n2XN3quYn7b$9L|%zdd~L2d$5tDgt5?|Ii0xw8o7$}aMRuxdd# zU+M}31_YGUkRc!DWDZzV2>n}H&rkF9b^#G@zd>vM<_86@8m)uyxKjO9QC~wrziVCK_`8yTjQb6OLkT7h=+Hi6Sl7)k|f# zv-g>u>7qSb{)-tWJid#VJ@W@!?Osta$!-J16K+|2d%kmoS|f#aDqr_eWmAKK3i`Sp zcasqaKsF)1KFL8E^9_@{L4F>n3W)xCm(ZQJgzrpv%LH|%0REj3)f}3c{_$}UIp+Gz zI>P*09rw}SpEQ%$zn~yU-xz4Gj6Nq1dOL(xbgpBJx}PlnP1?or1CF`t590I412%z$ z)JfJ^*+5y_I<`ND#?J*!BLpcwZmBfTEo_Lxqn$IZI%X|2^U~cJNJ$}pfNXn%ZdkN_ z6C#vL9+%F_E>pXoA;fqRzeC0p_dmxPunC}3S>)Vc;oV^3z=*XL+jXUim*iib<>>Rv1VKnFZ9~J`Ok>~Ar~~Pw2RSX+P052UCOJ(n>*Mt z16;_^l#rp1W9lsMvNfBA;oIqxz{z3SBR=p?p5bpvTgng$uPJ4V7w~qWuK9=mT&(Py zroffaYt3R5jE{820y!Drv<;y-Fc0wfb678n5~n?oWLWMBfY8zt^0bD+yCF{7(idkFFmVsr2+n<9R$}YiX&&3tm zYXi15;<76AfGfr0O1}t_RQH>E4r0 z*k+p4z%`YjxQ*fCX#MRRWe}YsRN70Jfd!1RcXY8u)cy|YR=D5-S@oKnTNVqlEanjP!DFAZ%eRWw4)CfK zBKmNvz;!A2W*L4oS|Sq0JPcj(6IKnv76bA^*!wkaZ6nOa9rKoj2kpdpHsZa?g(pUx z=^9T1gHd~pCLhKEi^27v=YdEyD%Eb6f0hRYSe}lsEf)QJ07tGkX2i_p)7u?tcwZmS&XCn( z5smG&*WW~oi~Td8Q`K>`4R0P0s!)8zdtSRILGM`c>IB?*d_iv8X&zM4Q$5P7<|KMR z0$sF~Spz;W=kqu?Z5+>yz*2ElG00=uSW%@0r}2U-OHHou zccF-=F~9OuVtm?^E@FE`ScIggC_l!Aax^$0jD6ZZCSQ-2U^r+r(UlcN587iba9_g*_r12EiL~TU8 z8Y1}W$&?bLH~$?SDeEx4MU;y&q4J&%)iGiC&GhEu%5+=FcB&*_m?EPx;}sA>TNqaJ zUKfk|>@&uzgEJK2cPj=&D3i838>+&Cje>Y|hBxLylJ?xTk4Hu1O$22L*d=+1K85_= z`@y1!|BIT15lcx)2`cE*`R>Q-S_1Qr-)QX~@W~fxU$fS`Do9;$q!kVV3l-d9BxSi_+ewJFiOA!T)i>(j1k{2j zu>^hLRKOXcWO|$D17ueH+9A%oIKc6QZGD^3{3d1j^+)#LCi!p$@s~7XW}mfnT)|sA zq(e5m-yxcES-iNm>}Ye1pU9x;Y@Nha(NBEt=;@caM_02Z9*H2F*&ARQMR*{mq<;cI z-FfnE+s+jhaY`^G2JBU66mjP@HpD?6@cvNGH(XpFJL~m2{#Z09Q_20Vz;dv>)DC~A z)LlI!akSk2Mwz4dwY9jD3ex>fc$a(S%h&Icso}RtVy@d9wwdDJmh9nnG^|xqIedNg zkr*CVQOS~Q)vj@M)))Uex(rAx!jltveP!pKWCiX_FwEPLy+aZ@!7M4q~vduV6(2?UNT`# zCt3Ch<##bjXi=d97E{w48NYsEM?}a|P2^Fc2Go;L?l=Zx-xpVvDn@D}u)V{jG8aNFa&{LiHs|0b9f_Mew4O#)+ z`PQ{_9#}E4l`*|IyQd!t#&#!ebM*vqmETr2zgFq22DJJKOU!6qWnw^~|J>AB)rfi$ zU#u#dgFuxXSH#&B4O1Lb2?uUyN=s}X5SJTrH`Zv#nSCyWzI>q|CuhKGcBqX18Y$Y~ z!9do~P=iv4?6(|*85KM?)2G_NT51@BhKb&>Cd3$H-Hcx%(u%1_J&ZE{!UW2 zUnHdt0m&0i2Ug^dFQ!oNSE)Q3+&Ugh&3lP#tahH1v6XMB$BQnVy$~IKc$a&VM%SXC zhXlv!-W{HuJWBpq9<|M^^J?Xk<00_48tPz@PYWSOC60o6a$vTSBBr45&-l>Zyi7}( z02EUx^OuTLNun_UDv6p3GKKt_ALM5OI(&e=m6r*w{X$? zYhYM^6KdOiC6CALu}pbBW&q{uUvLoO{ykp=;V~?hJD%VTlSg zMJi#5j@}y$pa(=}5)^CP&?wdrql;VXa?G6S1T!VHhJsRd4Q<;KejRkv^oMZYgm>C) zmqvEZjYG#%M*spaYnkAi1nY-C{Y~kA)<1-mJKjLWtEyy{l`TnvK(HQPt~>XGbV>v4 zO>>+iRaDrec5}w(zoPoyqNe@uq${v^+TmX+JVG_-`y2kOLt+$XppxCU3Sk!<+&M@3 z=kr3;n7DB!18tgD357Ld#$P@k|BhCwfSvmTF062&AbIWNdxp|?*UWgEDcZ)!%Es(r@qc zfqk&eFBuA75lV+IvHu~;kc@BftvVeF3!S;c%G;RGg?KKQc%~(aDY4n__+ge7eMkAi zejwXx;nSr3G5CY=yN7)(aaS!6>V#@?8|KZzES=o-!nLqH+U8r5&3!2n7y1{)NT9A zb#G3lD?8>cbM)YwMIJLNl;IErvhQwp6 zTMPA4^S<%ji<&}BR<-FbZ-GnSOsQRL@XCp(?%mM3!vK~Q6z8Zq>H{eP?iEL%J&82k z#o2r;&e_VNWO=DuV*(Rxu-icYr(SW>(RSq7$JZa1C(-+-rl*as?o)3cL~YkP6|gh2 zDtZbd{4LVm{(!kXXBhUd3vA5_NuM;>SO@&kxTGveKv@9wf0zZS zAPCf!K)Rk_OIOKHGF5bDy7{XzZB|6hn{=cmjU1fk9xEdh^!@&QVy))KH;drMSl!!R zZFPhFU+&3kW1nQhd;5FkI#m-1qRc-Bk_#}hi??<}xDnhOGxaQu`gT+@`9=nWab=XO zu%YPrZzMqlZNvgM5dfr~=rWefsAvG-9j3P3f;i*59VU+QqYni2-F-K4sWbT5_oFIA z`}2E~*4%F|aU-_G_PO_QYYPt+qyZcFe!E(WnkC|GD}ZKu(Qoj#kV8&qn+1nIOq9x{ zhpy%t1&Ax;jHd3qD`AN%PcVYTzuVStxbX?sXb8pK&d7xvt0N>>-jKs z)u2C6p}Iqwr@tTmw)4t#ovBtg*ih8Na+Adsvr8r|HZ~aE7yg=uRuLWfO zFur~Z`GZ%S9L`v7$A=Hhu4iljE4;a0O)%FA>*KrpgZp$yQ|i;nZ9ulmDMMGbg3s5) z)yMaZF1w!YW|Ehwf!ZT?Ob)81(iFe05`M>Rb&o#hL{5L!%5@~KXl3Pe8T~2S)!l70 zaVy+6Bqa_~MShEV6f!kML9bu`=8*GfiU-BQ@=!@lFW}KnIX*$%VzTSVy_gW7$|gnX z6jI$8Bv84<2JxbtuCZ;}#?^+^ibYgheC z0S{OFgUSe`k6_;Sdu&98jkJf;#`g(#LgOefax#1)JD?o6xr_9b$QSRMXbidG->EDt z6LfdvQ4w9+nmsaf2He@B_G_r+k= zFo=HTzkaqoixY!M3Qdi`nu5y|Y<-vtvAcV66pq;3d;)8kv+#^_zb;GL3N5 zEnfCDVf3OM^`&Q%_%VH_{^pxli4Fob0t6o*BLWVzBl6k77aC7E&Qe0W$UOy|rhxv= z$g^hU+(eHEC=UgpIlicAP+Li^P`e9zNUfsH0DWxguOA@rn_I8>Ft_VCL0VzeX?8kZ zI^@=u<$dmls?M=IS1!3PcM`*nUBC4L-LBN@ce7)s^{*CaB6;EWOJLtyPI+z|buf`WMK0YLyRL3H3mjtB=UOjR%u|PESCYCv7Q7lECf*A*-i3Cj z_&6Jt-J{thne_`*Zpo#s2P#WN{*`Ww-eD3~%i^X5dcmZOVfe4QfXXGJ#W^YWDcMDh zhu%60S6s6ka$+voW--@<`C00525&L}q(SOaUwEHkQI1iae}e5oCFVmY zy=V<6ua{;KDe@R17!`vA^mEyz6^Zf4HH|`EI%Fk0`{{e&W6v0~+~a#WwT>M84nMa< zS4Jp=<@I?N(GqBQ%b-+ui;lo$!Syut(axS_nW_#29`6UI&tykrI%kKQG4XrG?4{IK z+g;Qw1grY+JDCU0HG`c;!7lat3^yI?$;99_3*xx_a{(^3On!8wS@I9iLBqHK8xzv> zS{3caEy1+#(?nc*%+vi70)m4nE)3m*D=n|zfIPtl43_U@8r5yEiG24gbi7uSq-28; zwN?DZ@PR1ZQhYs<-=X5Zq=$rq127{@4UY``sb}kzN?Ckt83Z7s`!vtr&7mtICiN#! z8&q`1VEjHxQOo?JT?2s~4fieWLSteO#BmBhfCuKRiRX+X9Jnl!IRJE>?)c=rT_Vj= z1~vKB<~tf^s4H}1A|0}&R5=ob2VogXGiQryTW#>nY&o4TKjiK-oMIuy7f#&b^C42u zgB1f~V=Y39hX+fFppdT*8hksf7^k%nseTwD?F4U@ckaYh;As^`@$?nli6V_afE9i5ui-!lsitiN)fpZrOe*LbJjpdV%lxZkt z7_Y?)3<1|J$?#ya&!i0#)UnD7!r*z?m(AUQ!bTWT4`ToDtrPTJZ|pN2l@{W{8lS_$ zkSY0F*?D=$XH!6`{!lP)Shwi^IQEz&znAa6GUY2q76k?H&F+RPt~8CqY3F{ccxsz@ zBV_G-K{b?8fzegwW{Wwnv)^;IckDu}5%sWo3$U6oFe18&U>@JT&v_^_{d!|N} zWFya+Q5Apj4UO;Hj5^Svj}sPm)m9D>HY~T~rRN6s_i;{NS&FWmX zoUG7sL_hpE@Y%Po9guP@8DL^2WYy)oR-LXUIu_dlR42azY+YqebDKuJpVZ21Q7b-s zt`}~XX4R~)-V1vK=Jak6f;b@5y;K(jIyZ>??1FBk$E5kYzV2!%aeQzzX}BEzfX2PS zLks1*K>|q`Z&WD@XkzRm?v@opV zVJ$fod~u;+yx%71>Q3$`q5P@Um5BKiijbYC$d?g&xTF|*E#bc(E!M}hmEwT^MNa$Sfv}{>D{Dw z-O+||vpC?FCmen_>gw&5ZL~diynj544EocvsBd&PsvWJbSP(L+QLP`VzL-#7j`2*t zsm`R;0JT_iYMHF3UfT4#(Wm25=>sVx3-o$U&f_a0@6-2`Y3iJEDeix$`EE{EN!gYq z&)j~0Nn@9Hk8hku%5|;dVG!e!NppuosQ%RV5^hdDKDO2sINYeDy1n0CTv*!Okct=s zo_PoD5w5iA{AKCji{RUWr#pZ=r~chnYr*=eWN@FiE)a+q0Tb~DBp$)Gzi1xvDquW^ z36liQ#eT9rS!{1tFq%+`%3q}yI7#AODuNwyY}BF_r?;Q4$L_1$lUq0RXSmOf2e{5A zngqGF`wn#6POO%ECO^&uv|+q$XiBhFf&WO#@}^MDwq20e9b4b0@wIKs1OLkN8m!mj zyb-;2wd%W(-!vgopXANnp)(LoecF7x8R6P;(YMG@NGoPyfeIl0Y*r63>Q%@$P4_bN ztB;hI+59dlzI+#bFEph#3SpE}K3!L?&Q4;KqaH<|FF^0@{6`p9(i3|-}T8KMgTHJFTFTxIUOCc35?1zv!`CYSp*%u-Tr|D>cziE zj~Ijo(I78a0|@?QD;d(QFPEJhc~AI&u2G{@v6#{mZOoBEL?A~&H3VaL6&f7Sg7~dE zQ0S0Hu?Z3N`4j^)@$@1|!21BsnmXHN-h2hIzitpdTlDj*A*zk-;emmUhtt-mSPXSD z2k<%fX+K?;!XW3y@eR&e;i+0yP8G&-V=g%z`NyNzJb9ix*GCLp9h8Uszi@t^o(G@p zk_aFf^U64V4WDhYI}VZ?hjIuPa6hyOe?LCE!B%LDDX2kMiq24ES5hhwdq3TPKNa%+ zbx?sAn^a$8@E(Yc%TskZq3jr$7bn|x#IATpNCiL5vL$-G;(iNB)Tf`(YN2_mAY_ZK zZ*Jt2h7KBn8j`&R97a(L_p~70VEH6BBNb6%`Yj0+D(^zxSgeS__jn}KYLtTFS2aWG z3Ujbc{M`)b;|mUvCKpMjv|nxaBBb?=6) zWxc%k1n#!pS*^A#Tk3g>LIanRwx-fVx~NNOAfASP*dd{$^m?FK9WEnnW_De{z{KV_ zq=3(smzM2Jg37$%DV=Y5#pHGUVTyy@(|nZs3Qfo1S*d`y)2ryx?jDMCZ_6&o+EQ=V z!v8f5JD1^+5EAhOzD$Dc^({&OAoH~*I5YI7%J!7d7wh02-FU(-z1Wq}`y*w^Ow!65 z8_qF}RX<{Rl^?Ydi6>7?#-07~RyWIRO~_IRWQ?^KJQgxC zB4cHHilV1V2VE^3*PYdv+O>mG*Dp#FGD}K`){Vx#>MZ$O)Dv|Igk;>W1^GS<1X#1M z5=`Kv44hPjd2)t*g`c>Ga6Xcd=KU+`BY% z@)&Wu>WZ3`@dcGEAk+JUvCwFFi^(9+`laG;YTDldh+X(0;!hD36uc4Qxbpb+WEh*u zUNtcbVjnvxRd7kO*%d-|N_Epr90e)_aa5_7)!$Gyo*k(BPKx+CQ+QpMXpeM;^vYEe zy{OZg_Fh9R^k2+oG!5(+hI=XLuV#eoATs)*y|_K{V`72H34*EkfuQH|aB|q#qXokw zY<5&UKe{C%7hk}2m!lC-R`uxHv?^XKcx1^hbfFgrV~Y^oGHvn&-QG$TIv$VhXWO5q zwu;De*&04?CZqmY@sm_iT7FiY4gh3gLqD9-TB)+*motm3VXq)8aWExd*lv^h^Hz-! zjk!1Nq{i|W`!SOaDPXGpy@+U~lCJZeJ0Vcau2Wvrv9?Eoc8D9ORdHpfsiT-^GV165 z5p|YvQMJ+9e*~58u0cQqq@`QByK5+EhVCI$TDrTXyBnmtq`SMj;oW%N-#K6B)6DFB zuY1LH{TCZXJlM7RQy*Q>fFn+j1r;J9V!2UoSVr8OO9p=3%NFJ186%@b=LbL7{sR6T zyny6fZZ;b)Phm4Ls`+Zu0yWX5+EOl=`>u`L)na8dW+(f6tdC&b_slKmaj0Pltm^e% zfst~>8(~QyL}hpHqA+={a5uO!!`dIuL zr}g52wIL4=y+k8I_LXHqn^H2pXfX54qmBRxZ??gK>Ss=EE$GF~nZdg8Nz-bf0WDLE z_i88I!8fkT^4rz)-K?8Fy_R%#)tfSpJG?_i>tj~*if5Ot%qwni6cogPzDBzkw~7dh z27As2zB|~k-8hk(DU2hcDWdD*pw$yk3|ZKQ%j<^bg}ePYooN-{{tqbYZl3LDDI1eZF`KWa>ux)B84YjJV0@Fv zeC(MG6Y}6Hb6XM98N5(Sa->pOEu9}%nU7w3@~+?Ab_=NE>$pC9V06gk!EVK})e3L> zP^vnuE?zE7*pBQ4m03ly7}HckO2i?x!mEP?XS((p;F?OFjjQwL@fM zc;^oyyk3o)Zgg5V72BJ!FY^fs;W3zK7l)JFB`Hk zF=`)Ty1IMx=LMJZRvxEL+&3fPfM=zsEpDfI(NAHds^{5%w%kiw8qaMe;i6r119QLEw=n`G#(01WqrD9Uas$ zYuSp@&+F4WdX+8?2QKVCx@LAI>Il!;QAv+@jUC+A-`{niqs=E#CxNw|oT?SGJgi^9>2d)7_;L!ja~a z#-$0GFh<^TX?>wW9K5zT3GJ-cbdN|KJ|TI}5^P*#-s40dEB^T`-D~%%PvVU0JasXT zQ3ML+1dby-P=s}b^2UHltcp{6n8zy;SoUD(C;zG+XN%alkWRWAEaW?O9ji)NSy`q{ z$AL^J*3+>@w|*Fo5*zeK@~xNKJ@*nhcU4;|G6~uz0}i+E3JS{F0Zk{~I0BE=pv=wu zIV@&JTgGtnb>=V&zl2!yqvj5J*^`Y8BfCe%XpDn3h*~d0sZDZ7Nef`r#Kyz3ETb*5 zC^vaRfob@92ojF2&s$ zv_$v7>VdVbkqW*hb)UKx3ML;a=?9cGwzym`4JO1lVm8ofEBwXOE1h{h7~TPZd2uip zBqS>=Oabz~r#Mtw-ce9oS*7n#w|>HX_@yH(sY${g&}})Mi=@_e!1is{m2!wgF_-e= z%Ob|Jb_c*l&hfK=%WBL;Wo+g~!_zrKpDsqSUWBkj3E6fqD>Hjteh7Ea6Ixx-KBcZb z)J1I=Yc54|u<=!IW-sop>0ECKwX|N$(Cm}Cy6Xf8BI-YG{z)!$S5XqsXJ89dCTh1x zj}zI@0r3N4_*~oto6Uu-y690{mY>y$4y~>bU7Tw?o0|j^RjYx%IznGQ=z=4}hN^G@VBT++uWlFOQBcIk5Ry^7ed(-UT;^-B9Nh zR0&yu$H1TBOG3EzkROITTYrSok1a2VnqD1-ePU zye6MIh6oe<8=Hv|f#Fv=f+~eywD+D$gnm_(XjG8zqWY&co!d=!d-u*?@r)~N5~uQ- zkBC$rrWvWN_FO_sp-u}x3hJl!> zOLF#QR3Xkd&(2wkkr+Bw2H;2ZemlcqYH9Im@oCs-!yH0T2rocW>a6B|zOF~eFSYi}r17THtRN`TCQvGlj!Vi%$@yj? z|11`6X5gJv+*k{ z-x_>*4K9DT0aSWvSiSRo2SCKI+l}0vf&`A+ zN4vXbA^7t%mhL*mrV`B)qbsR*MCG(A4!b39o}l`t8Q|QSU$&^;isgVOe4}OtY^e&@ zgBCoqHUb5UdFl@KxQ7J=0Ym2$pMrr4D}XTqN~d!t+{%4?`nsFB2#Sx6m0(x5g7rY$ zo85IKF5%vJWRlgq-PnKCi>|-%W7*r67_!Js^~V(BYFt64v@rB6qbuDKR+yUkPaChX z2Z9>+)o?aUqZV;=I`4$L906#oUznvwM~7i_{tS{--_L0M`eaU2R^@8~>~XwGs%yy2 zeGh3z3!cuZF2)3WEge2^SC>g(Z5usD>xCw%U~DFG5)v9oTnrck(5K?&X5v?ppG41? z*ZH0N=~;97n9}{ta62U)DAf1usO>IJa$C=QD$=;prLDE}qgz^Nr+&i@3D+JB@(IsW z@4%S&oXywQ`j6eOBhk@#Q&IK&9o4*fO5(gSG$Hgn`|C!OHW-`E8%aUeWQC}BLaE(~ zGO7gqtj6<&aB@J8a1`3 z=2S9G#1+iXv}nP$*8Q*-&nRDw?G%DN3| z=sA{DVrEBPM><`mSLSEh2B5tmxM>iR&Rjltl;ssjv1*NRa9Kr$BgZuke`! zN@`Cznxk`n(Xg|c8Y!J=$SsAzVM|*pN=z)kA8UI@swNy1H4hoMCRb5WQ(FgE7k_f% z!M}jzIm*x#@ZmfO;pqMkkCU{Rdod(C%hF?HbyIOji)r9}=0tBkDjKQ4U6jjlv1mT} z+TE18-Wp(B>8M-rB8oe!nkioS!Putl7x&@kT_43K_bo2zv!>UsQ7M^YBqBY|C@^hL z;CHmHlPv-Y-|I6CUcG@r9SkUG<_69mc&jS4Zu~O<#)U{yWERCV$=11jM|@fw)}54lky<)GQvkZ zWtXu~*ek;1pT-mdY*hkwr8G@CKOGFkqy?g(=cdNwGURK#6>a&O{Z2dQJEm3$BQx=C zOPP6(TaDAyt$F7Tcs8rRTJn{zu(F8e%CjX|Ag4#gBnDrk^DhzYCxu>*;56`&;= zV41foXfC;rLPU+(r09NyP*VMdihoK7YYS`z9Gs_GwS@ztUNqqs&wRAnsaRlb?IM!k zqOw*(fI}owpV($ge~$W=!#75*?vPa`k#*AY{y9o_)=A%|cg#|V`fYV9s0q1`Bu}*I zRx7r$^Np{5*}rTS9)QECMv~=QJp{mA5eAqQJu1PPH$*)IXHYK{y$v1S@oF-dbzWJ( z7<0N(oo(>u8&Xm8qb{B)@YTBd%zODq_ZCRBE4*L4wjedQKml!_3OgW-?zyhgg|X zOx0}7#ZVycVh~gKUkUcvvac@K@OK`$ z@Mm=CqFwGyz(s$O6{@pdVnxgKB@V{H!!rUvHM5n*!D^We04*l3&sshzdShHGD>i}U zVC3);4Co6b-^9xXN{bmb?-Y0fvow6}{PI2f>#;US{tc!Nv1*MzkAih}n2M!{gLHSboMiW#7&Z58GODg#V5;W@PYLv+EjQ?c zIW%SLV?|j51IKyj9MMcZ`Wih@kzwD4p z=N3XRSP{61RUL?KGiqahzUs!)3jr4ADkIf_0B+Sjbkq-a?{px# zeCOBixSZAgyT7?A9-}8O&W1N;dAhI7GD}L{0pG!F;iRcnV67{~;IZ0YrRUxJ3wbTu7c2UxDaJhPD;j+V$G&%nb9fG)u6)UyjB?C2|L)5c(_bG?Vf zv>K_rbILG(o+blwkI#Z@1mvHEYT3IC%~hy{+ZGZrI`6aCCMTy2#-mWc6B|ZYune@l z+j%JI?pr$p^$XAW%Bf`Aw#NO+xZ%JdZ!7k*LBa$vzUvZV8?mFNrYRDVjx>8;@Y5Q% zl*pOBC+x|R+2jvd?saKfChpjCmjfUQ&JE>mPq#frQ=dlw`U61mEcSXW2tRg2VVTjE zHv&V4Z+X|(D}8I9kxlAW!+AgK*w}4xKIlRMMXGcKAy@qLG`d8%y$N~*ctk$dnk8uB z>|d-T^yp`*i<`H|sWJQZ(tdcgRE-l#Nz+ys&G47)bw0=-)LUh9%Rv#Fi!`OFYXt~n z&`S%?kC8Fn&v5~031vPnen+5W&&f`?e#Swl(e ze`62)#~+8v3)%N9`e1WE?#^@HutYgj!)SV`=l^!KNB3+0{mXgH`2_+KbgC~}Re@Pv zX0CSfu#GI7wAY!FM`bjW{|25C_TEXnt#xU9oPfjqzb{{u#t64x>fb-0#kk4@hf8+V z3s%7}(BiZ_+~998%l>MRP3P@6u`fkG?K>l{qwEa07A!8PtPPwo3$RSGVBizPy~wZ8P#6Xj>e z8a(e(y4m#0J!aqb-Ti~_tq5gG6>l9v0r8Q5DZ7S}aS4_>}gzHz9Vf%kX(V^LpXM)-n~Rpg1+=TkH4O zyp~coVu&mc&!KLBb1q!4O09tN0A*kmNE(c~i1BX@ukl*Ip}57=I4w&*Zvdh|_s}5A zPt1IQ9r{veQ!1_~EkxLAXdBKVRd;2Kf{<$e9xas_cYk^5SsO(=0-@mos*zJd`9c?^I&!pWAl}KaaPD>Os;8?=#N@(DMuy5~|C3mr zUa0RV(r;R!v^BZV0@y`>(iE3b+gjMaU`3g+R)#fbNLY+#E`&Frb^!EYzFJ@F>ji^y zi#GzSUcV^@G7!`)W^qTz)f#i)aP94s4rg<1m)ispMn9y~(4)M81Zg<4oqFggGp-eW zS}XQls>Dggu=x19+@o&6|^Dp7o=@%k-4TD?{pzPycc0il`sT@&06L*{|M&PloHgcT@f>6qw8n~fhH z)#rg*_&s7fyId7f8l;*!n7Q`ji}MZxk&$`L_lr?}7*D86Gr0jEer~rDmlLwgFD&h@ z6L>sidrIh!|G-ldpQ>usQP@1-ptIrcFLt=Byz0V5^TB!Swtd&^_eU!IS#;=1C}Y;7 zY5b_oCkA%KDPU3Yk zHU@vqoFn}L)3_3E+g4IAnRxl5(8ryCHXb=861A)f~<~W!yQIQwMmwj){P=XN73Vnti9H=ONTNqLE zApe{l+^`~x^Yk-IPP*&b%Uc69X?L`0v#%^(cm$%?dy%ZOwokwQjj9CT$hpQlQGpo; znBW19A;VF;v7%p7N!P5r`cT=47kGzP4nDon#~j#Zr;*|f0Wr;4E?^ewYLe)G*vGZM z>+W66Kp^RTaO)UXwq36%p+&5<7-nBQ4aif_J0bYO3te~Hwa!kem5ZSu46$gWzx>Ujfbog$a@b;iP6QM2^= z>L0(SZH%=AjH;M$A!vShrCA|h{resL5nRrM(;U;8&4shxIyFLEzgdw2C)kixjbOEW z8EvWr&WhWv&5UsSzE1eGc7DuaL#wtIG|h4IHa_4u>RIM}S!<)Gq~yYQxqrZskcQ~i zY}RJPV?u70o(`tB*oz!C_V5HcTVcCF(b=)4cGtcatG2T*iE_W>h1*gT!4plUaHzq3 z0}{YHC@Uro$ZJr=Ntg?!gtLu*Q&NyEKinGUTz|EaX|9uChi0HmB$w~Gq2kh@PxED` zm(AI)@;vMB0uM#P_ceB7F2&3-kffwUfS5$s`9+1CFd~wqGR$~{{8P)Vif+JQv*1%J zT@lNRtgMLW@j=>ex}Py@7MtPL41200U&TV7<;^#rMS?V*d->uGTxn^4*eq7U*)%`3 z%sA4>%;Z7;IC`L^?CS{|wai?eclDIg%WA^~FKaa#=a9{@ zhE?g@D2ox7jI`m)Gdd{4BAp@IoER`OtAHXi;s&Z!!``VrYaO}RfsallGbw+ty{R}dH%fRc@<)2KrBMF-m5&$)Bii4k-+QYk;9=lS_n5vk>at@SYYRA%7q6*>nh!nT1+XLYZDn&s-kn2@q zax9*sy@+d?F)2gKsoCSfGHpb}SR=PgPEKt7aa^8)j?yvPNd$8q1y?&u(VxPVZr=Ch z!U+9~#bn?kwdZCMV`DEN5He7bVz;%fQj7eVfk-MT@p?h`0CZ2=)yUL*qkHq!vxiDD z;!>j-+;3;UkO?7H@;ZA^JG4ST% zYR9Jig+|^?CnZ(NYE96e{{A5qZ!PknRK#BCfEc=7@v`H++-a&uf04w|e4>)_Wg{u~ zq)8GRPAl)h=H{{$e1VD`qrbIZQtqR&+IrPkWjh-(y@M7&cqjFHWBoGP)b}@qXwL|^ z)*^W3vZv?0Q^RWb#x0sW6}mhMG>R=ewD`7EX^%LYKDK-PA}sSFbnD3(#1Xs-29JJ z2**cx;Ugv28?>jRFU^mWvVBM6jcWl~9T{)?UgR>gFfth92Cxo}a^C%wd30 z_3x&wl=$&srnj-gFfFlI%U}~0zN+_bve8F}i>YW$j)QWYZKTbFfCmjjGBBZSW7{E; zFzeSra@}EfSn5MduFK%A-{ECiTGs5F6%4}Tt)Vniy}J?msmIC`UvqhoS4!EZNT)xq zIjY>-*Pr;74PE6|=&yMp8N=0p)h|~%%L+abtCrf^d!Vd={3Mj4P1n9s4rr<|n$PZ#Pnx3l-JOFIMVrtGcwkF2AIHO~SiR*cVM$GSECDELcTzB04 zPMtU3?QodbbF8ddL5KE-6^E#o*@>jYuN#n;MKoqmJClWo9v~a5!C;}AJO3^JYZAo;Jgnoj{4%)u2tMk+&Z&SZoSStPAs`!lo5$egcZ>F zDJ7#7YgA$H{{B7h%RVnQPJDJrgwy~dpBwD<^9h4YIycN(pJ$vC2)g-^?)LJ{b4b#1ej%jNvaw(W{8HS4~%7(~h6Te&D&au-mh*zGS5C0)Cyk{P|BE4jMaU87w~TFRsz0ie=H(FKf3t!6xR9f=SmnEh1EEz& z?cXKT36DItEH{I^8;?Oaho`d63I7|SfE1aNGTYAFrQ6kLKQn2OSrAZLv?fDI`Mqx# zIgh&b$PhB)B2JM;5<~q4ik{AhT-GvzgoQp0iDoR_-NaWocAJ#Bk^dawTSt?SGHc;b z{oHYL!aQ$zpG8TepopPU>8TO}Yno;c4_3-zqpkA1ObFbn13$v%f>@C=e>Z0#B6-iR z;xLdBkp%Qpm{^jShW)2V5chL_y$qO899ZRb>*;0QEwS7ejL;1_n(WOXDtaIR;YBFq zHAVdyLeDlPC!BY$4pv3xX|EW6(_>ev7&beP{`)^3kCuv45LAZAFNu3~j}rF3GJ`_> zqszmz$lwiBeqgX7D@y`$JI`jn;y&neZFN8;4X=B75Vz91qD%9a3)eMOlsDbJqkW*$n@SAzB)C?n7J3*7w-)`fl!GFGBejX|aXBZi(a`hofWPdG z*@Kq0#{G=yy2WA1$vZ((9q%k$5=uV5mX~Vk5boR`M9?R7WIm;Xh#_*VVF>&M5^yd1&p`}b!)CM`D>N>la}Vcq`L!1%jDB2d+# z4$wFM30S8mDP!9iTW+D;kGRbMc|J4F)~8$W;&nXUSqH6N zR%6e0&=O1~FuL8ak?*WgPYe0oHHP=Aw8+L5O?ZnB^=?)Wj)DykwuPb0gikzaL5sjV zOBYUWif;lqiH9M>GX}~JA8fUn%Sy`B+T`Pm7W-`$;f){uRp1e?SsWr}uO&|h`RC7{ zGL~cDHfR4Ey<}U5psq{K8C0O?&CjI36$Dx7(N@lfh3m)^6)xW&f|u?$LNw#o&s?4l zEAltF1s=N|0K<}giroO2nT-hi&34TT&W;0L{w~QbYF`obEy1v-{7QkuYHJ&eIr{x;ilbn0g5^-)tawN_<*lD8) zLYGj#{rvVD*U~A|@mV7!=TlqV{Vnr2GpF0OpVU{h(Ur7o71{twp&L0{@G9 z;`vzXH<~14y5)zm+xHarBq0jX`02j{8#Y>UZI&wJ-PT+(*+fJ|4W`MAm`_^T)_rD< z$2tl&Hni3IG<_fac7}RpNS{a;1ss$$M62MRdeakwpK#yJ`(F|U2X&%Obae6AKN|EI zv-?_ht|dO}ryTtdrHbu*u^RPcZz;3P7X`=#9!!LvW zG)Ydi|I@Tjru|hseZtqSKA!Pi7-KK3bd2i>=5N!(e*j{$`!7!N=_FG6=Wq>*#xLX} zaV3i(+9&Sql@w$Ey6M?*4Z3Tp_{5DZF?&O1G;*2*R#Wqf2fuv&*el+3j?gR99#Hmz zP=w3t|8Vlm7M93@u*XhoD-F6&%mZa@<&J4t;HTSS^(CCIswyKm%eprxAK6Tz>`k% z)zt)mo*Fi4-3)s^YUf~bn3s@!>m>To>ZyN6V4QbYjcZsj%uL5?U05pPN{};=^HO5? zLPu43npL)I{lUSz%Sk=;XFDteClM_W+l+|29?!aY8?XL(A8<)3=lKb}mNw9HL`5a7 zp!s?3l6^N5F~s}pV}AqT`ww;Ex$JVzoEL+`eRmIQi+-HtZC#dNB_TvqkZ1KaB+ePM z)5ephX*OVI?Y=<}S0e9B2yI2ykgLTgh3I(8$Pj-~a@W@zXV*YKVi#zW`}de}UrQKx zaTE^)*mos5>T?oi0u4Obf?2OWlf4|$ zUMScwJ73(Av5b}Vq94_CYM{$_m+1}mpweaQvj>{dzB#Hg(?E(in~e5E)1Cgs_OD}s zhdlL3_g!RtE$CA>MM4sGeSQq@+xTsoGKcJNH)y8nHoMJao=)XF50dIq6qVtU&$eaS zT}|7VO?;oT{&ZKg?L-5b1=^X(H!D+&QOoJ0uj*fU8xGiyd%D%1gfG~&gSG+Cj}CO+ z`*cAWR27ei4kMRn7s@VH?WVWlZo}_Yi7(&CLg6=IB1~&nUZXq4=ku=YmeJ1H^ zeCQmfN-|g89P!U17RLp&=kt^&3?h;;k=9X_ZPS(Z*;Eo)w2#{l7h z0wiy*2DcDWp?1a|kJq7eIzNwKWF&xekJTx5(Lf-OHOD&&)kP)dIU-JRzAd9~8PKlX zTKh>0>WbP*9!ta!yzavy)t^r}I0JnAD&oKDOoGB?J8a~<@O$MNWS}J0mz}KDquAea zUBho^*CxuE&zvM^4aK?jJlinkTTUCe`Ipo0Hia2_LYT#&Ax6h!79_Za1m#1X{>;A@ zZs#Y9+4`>HQX-BmYmr-K_>DSV7Z#-A|ErM;=W9n?@~RYxj&t@}4APe1ma}xFc-6`4 zslHXY%&EgWXMA2_-%b`SXBFEp()Vjy7G?oB982!wgC4tj_dUq=v z^JjaAR?Cfe9FJ!N*tl*kfmcKO!NFloZ|v+4hGVOiTwPO=KV{7kp;!tY9Z)~;-RCC$ zkc&;APES-Tp|yJzzN1V3dmbL0wK3Y+m?Je;Y_-jHIS-3QY(x=R27WxSP^fOGEF`2q zvgbxE`2E_C>7B%Gdqp=AXFRn`xgagQths@Z3(A@E0p;VbD=F=93w#lJKZ&fNgrhBw z1fM?_jcZaX3f(PAANL-4KQI;+9ndWRNvAK*h&NoXdDt7X_S%|l>^y8d*#z9y}K-f zRlt;^fWbsuQ8oHrYe&ss(LtoTN~o;cR=%Z~NZq6><$hLkEgm)U;%uv4_?qkLeqD^q z1^S@zN7h>)Z|Nn#Th4ZS;r^mTbMG&}AF4P}+5shf*{$+129#;_59{I8ZJF1sJf6+C zLpU=5*ZlCkvMobU5{ov07Yl-E$YRill&~kPb<+c-$9=cb;09~+i7T*sqnPl5_09Y>Dv)ZmxIb$wapWei2EfN>MjGp-8Q?k#r@s2MDqJzKWiX-+( zK``9>3d~t&V5wb5(Z~kfPS-&4oP~f)0B~KhEB=or4GfZ*lf6}Nm ztTOJlN?in+KbF%cc6SJ9dbHGT*MkF)Dz1klSu$zc!Cn0idso zG?n5`^#-`*!T;jun}20Z{lbWPoK@Z#z;XkIbuwj{9*=9)_HP;yF42!|XQ4K@ecQG7 zk6M%oqI5g4lOO1rai1C~$tcNk`yb536AoDO(bQBY^0$Q5rzK?E9fVu7+xM6|xM>*X8wbU~=Sfud37Syu9BsU-00Z;&scdhDn!?G`m;6Zss z#Wm>Iaq(mtr}1`8{qd!#ZN$DKLalwRs<%}BUM$~R0R5!V5Cb>*0f)lYC-sfzS2R zs7=9vW#|-n6!kf^mG~@h=E=HHnLqrt{P1hER=F&5+=ROt;{vPntfh>;DZN>DZNy(R zwY9sJe^fo$UyMqsXg@L%JAhwPQg$u3XRBJ4$0NXx!{Q*n^BPt)sh69N<~<(^W<)j} zGehGZg`2N+6BYN=wEGTndn#U=Z=S$C%ku5M!Q|A8mbG|u!;QcrE}#y*xdl448@}08 z6rXZE?=M6`0>`2I;$#qUtoY^LBjAGYj=}i zM*n%#hN5h&Dyi1@i@?L*9Zr*xkHmaXOzzL*&y?wR@;A*P#ony)({ z$cZ;gg&Y-mf9yjpJqJKOM}~o~akT;#ngetq&!43Z*_Z9~Q@5SMzMzq99?;CLOjNiU zKz^C(CA19vXdda=+n)J3zCh=F6RTphH*FY0!{}gb0@HITEsVCM8|D&h(~_!4hqN_? zqUCh__?OU8I#^t9Yb{K9eSQz@ts?`2ntqBT1Muw9K{{E zH$b2EwXWl|>cRi^n~I{&6!-pe-=DvwiL4d}Y>u%f9m5H3FiBP`KFrG@QdCki*Zey0 zD`8gyz_9`_+y+=6BZU!Hsm?iN#y$OllzELg@wb2((iQZI1NFF`Z~({Vx*T$6pe$Xs zQz4yo33vxTdpe+>_1!@;;9XX32-7^)l!3ZO)Wm{A=PJ0#c5;%%pjc-WdF_X7M_V8} zsY_nC)7$%!h~~q~&Er-R8@P+)SFu|Juy3ys(Y|y6B;hjie3f5FBW$JQd?DhUIr~GX z62gnJfHG5?bj*mnFms?qiG72uYH&4zIXTH@kvR*8HY^f%PIr)Yy?uIMQfNU~t{7x| zCbJViWzjGJhcY1YVlA20sYP&}1`yH#j=@RSAF$C`-@*(WzEnu;$$JJepW=sxx;6^{;vZbzn@rM z-i~IWqWATdQi|I+-|a~>hv96*a-hm@r6%M8r-`Fc!>dLT{)J%`&^C|P(_43^6SM|& z61iZb)oM2#7}oO{n)OR}gO-rgr&mpInP%`rPW|d7VD3 z(2t5;%@oYh{{A3p+A z`&L)sx@DLRL423oO5**l&7Ydb#73nKxFeAB08J@)OI!(iRNNsqBB&Z+dFz1>|6xZdfuVr>sUi|gB;8fJN$84 zlm-F>DSU3;8OSM9@P}Dl9l!2m#ER?;C0b5)CMpEw_okUp3*M|O;<&Ug<4ne}PSpAN zQ~q62LE)lm_9>V<F`tkg{va!9|WA9ImN~*@8_ph8@agjdcCZ zTd%ukpdyY z{dsJTz|dZ7g#MONiq1xDVZK1bIrLmf8vkaOpI{#Uuk2m2|Miz|YN`;Q+NZa&Dm<)Z zXK9bJx9;6UvpLVl!z;yZLPUg~NWZ7a!CPK@Vg}#Z_7d2Ri9?8)NSMdZc8BmEe(3aO zV;s0JbWxn>`~cwB?{xT?nNjgldEn~6-nc-g#QMO)8i71cTI%!ZRvm4P#oWqEIU&Hz zcoQGJ4#^|Fr`3UO>(%_!Z?$EAf(u8tILh%;@JBhb(vkmT3)#@Suq?WHzfZJp+u3Gn z*jd`GR%J^2fcU?q1T7itkyM()9}96<_pt7#c<&Nl6I>x#OTVhKme|13`~q=7w@}=q z)Xe4<%(zr+QXgtkL(OG&>a%KdJ-@hzlsw+y0)&c$!sfxKHo8HrqbgrL>4m8#>GG$q zIos`^IUW>>SaBZ8cAODQZ1O9Bhx1v!+O^VH$U=zN-Sm@r<~j(pn|sA!2;doS?dNE3 z&7Vv;GkCMe@yCR091T4_-#e1}gXe^6g!H&HVVNB!3-A+o~J`gGk= zT-LkgZPZt82Ep$-ivjMypS`@HE?}o4Ot$~c#i5Eh8F`$`G52@0SoOQ$vUsDr0s7g} z<-rF1fZ}Rm9s9qec0I*|)tPxorx?uZWND#U1pHn0*^)Ay+MExUTAjUmEmWPigr~_X zI@;=?mZYgakK6>3O(m7ukh@6g;a>kqGQn5<9;VWVLuq3p7&aNnp)MbFuYfmvVic3r zBAnW?EWz97``jv%Q$+#$V#5=(pQdu0&>SXM8nW-oHUp%nuSc7HvDsAks>-YVY>-!r z!UT=S382?V{THmi?4BV+i~H&5)Ai^i@BEkJDt~Q!iLh#w<>ffNFd@qAD&_UaY~C5Z ziRdKzB4CQl?4fp@DTd$&SepSVgnHV(Jp_53?~bT~%?9Ul(csi0;vwU5knilrOSSd- zHg0R?f#l|mKkmatyv3u~!~liqH>GJdi~g7v{XGVU#TTQU?;d3rajk)Q0*x43s(!W8 zIHY*N7@ZFv*tjs}G|f59*3pMj*fFE2P=%w;S%D3vRndL&o7*pJ5b2yJz^|JKB$@UY(p}#+9c&b&^ zX+9WX);20!6P1>X-cS^VE{xACR1?Vwl#!%86ncMe@k>5i2%su(Xv6;WJ5Jc!`0k$~ zO~SyA2~hTMjuP^q6j^>&P--QG_p!B>jASY@-@ZAk7?)5>Tc(b789q8aPf*KCTSSYQ z*53*vKU5{>WT8Z@61)EM{kT8rc1n#*=ubJrnf{4F+LkI$u%e1)u-9Bar@KxmX2+RU zeT^ck#6t7Bh1CG9Z~^8e-(M`du|HPdsCq5${>pWlGCf}5abA?%i-m)f zOR}VrZK9Qv*}7>dRwT@*NJPLc2uQp(UkgnUze-*nlmjBm3d0L^d=4{Q;x(yt4NH(PSZDxeEAj|vd3HKl7u-OB=IZQTuYB4sXH`h z_Iur*AA2o|bS}>0hX>hj5h*yl1X^1evni?yN-#&GE<6Vr^*YgtR@%h{_`^b*;xk(L zZN2PXYY%E_x+xjchY?utQDMXA= zYY`DvnPxXDOAW0YG3#myp4Id>B$_tHNkYl<>uuN*&;b3X*ULC|myDjiZmEW#q57}q zg!E6rB;Rf9OjI_1jRLftBGKbR6pVTg4y#f%iSd0)g}skheNBmS5!O|SQlfuZZ5hYu zm>9|BXodvkYt$EfE$X8OZ5Iq!E{Y>;Q+sY%S9~CU+|i}%V=NNWG9>nqrJC+RcGCmcxM~?HxcU9I5{|X z1JYKEJDf2R<7JndRw0B;IK47Fq!Z$#p)p;KkTfqZR+LT?-pHl095Y=5w~|kBqO5~l zi+p^bJxOLQDl{2GKzCtR%5C7t3e|xf<}uWQE9Rl)WvX_NcRyUqu(b%E4>Mq_Ld)Y$Fl?A)-jFj{V%fGXv6I8s0P z>(#MEk)@|D6Pc0%Ju(17=nT>bKT&H50tgc`zk>R&6xD5LA2LNnxUwROyX@Lh3^>0% z_H&xuS|K0t$>~N*f_BO@O$VTn*MHBH71VsPesOQ&s98epUF3yUtR+i5JhBz8DU$f! zRteG(<*~K6xTja4=GA@opHN1IrohRKZiPnYAl`>tE(f6D|67LQi||iVNcCvg6nb!Q zps=D5U~51-GxszjC6kyk61P5APm!JY-WbUrJDHJ2!peBG8dlI#HYN?eTN zqdlEEkFRh)xOpwRq>4aAfko;ejuZOw{6G zY`3~6r<7^VT@Lb~OhAf-EUW(jYa-y!aiApjR|JLzS&aCwr$&FhXe3%X_}lg|ynaxiU5#Cfn&IqzOPNh&V=1O(t@nu$!+c$QIPm=Ux?aPDuL`Nw??dw02xMbbzx<*i zF;3=Rrd5IGQzJ91Rj#$z{jJSIxuNcX=7S_QX;hsGIbFT(hw+(-0XIVi*i^Y!8UX8$ zbDS6fW&yAqc2!iQHndFi-ggM0XK9jGk@znY5v(+OkC+XcgmB?l*8V@HzWK4P?)kbw z+t_Su+qN1tY0Tc(HlNsPn;SG{;~P6^Y~#kZZG3O?d4G8Sg0s&#d(W(yy=JY^zMN|k zt4&dPF9`@a5#rRcfM#T>E@fe30XZNwI?5DZmL&A$wh!}Q&#B}7HHd}%5IwOlDYz1? zunU^tXwKBY)*l+(>eE%Apuo7Ngu% z`aMOJ{O97F>$EBw)gWj&Wac2%R@BG`D|DxTlz~bK-bXXGRsC~xOOlaWh-q!=+=`)2 z(8eG?Wv{fcox9Wnin3)wEVFWTQ;$;jIq1Z!N zcdvT`!EGr*7QG*bSGeO$%etk|tk_i{bh%|X-GN{w5;?DmiT1V;8?pS<%mAV#Knleo($kE@<@2L8YhsduOYAO{U_CR z<*DT18TV|!fs-yD5Py}>^l8Xyi{UrZ|0Z+ZXkb>d8P&&w3yT*TmIhS~w2NFl&=|70 zH6E={u(d0nSR<^ezi}htd$ha%^VUW^P0?p@L7O7SF4?rqm_3Lyewy^Pr5soKceSwE zf^+oqW<_XX34K%Lcp)cUX4^e%y|uFJ5tgB(yi0hSto(Z?A2T(Agja!;k!H&fF_A>* z7>!itV6i@6N%vOshrJ3H#&4}rIpu%h29|q?iFvT@H8`WT!=`pRxGk+iJC+89D5U~X z(CLc-C|$9>)-|0WI6h^i#P5Z|TZSu9$+xMlk~rcts5eH3*bj6=d;%xF437$5c2y#q zSMNTg&8~=KHjWp>;E~)g^+n#)+mckoV3ro>mT_Z2H!?}pi7f9|*p{$`(%``sfPMa{ zR_gAb0FSavL)@pB=d6si3cJoy(omGqj}wAU9a@#cV`h7a;^G`Fx@5JbRQ7i3J(6y* zo4YS=o)F&pMn?BpVkvuICV0AtN@BngaK-f2Uqf8Se(mZUY}|GqRKNG=zOj5tJb97E z^uzD}8(6vcki^i8#(ia_tqujWc_MuFjt!uI^E{LX^FG(yQknSLQT%u2dWSKn`07~~ zX6c_^;MSYSS4OjFwQK$7rJ%m9Y|ORc_2FRHp|f7pF7XpPgWLxov)*Rxot1fp84h^# zA5ByHX-9a)GM7MGYe6Fc0Yi(fXCYB&;-8*s=D)^?TCuiDLN^PZ=t-`~O128;*WN=Q zQ^Q7_rez)h_%5gKiF-;eF^i@4pEGt+!IC(q1U z-%5m5?npXg;+pK3lZfgEMn91xjyq3VqEy=#!Zt}~E$(9be^yQHw;IJWcVNrPXpS@H z`BRiCgB37RA&ei771mhq*t*L-TFAwL7t@sh0~L-XyrZmA_&M68uvGOFXf+h~q1HrL&rN{S zrEaH8Qp&ZcVu$J-&%b#{>7(NhNjat4roV2h_vk>pkFZ9~b`3#y7@bV|y@j6_E@A*x za^D^=fghjJlwgm2Z<_i43?+XQS!2>D-O;ri&#KfJ*Vqdf@l*=BE=@Bv-)8?=~=}BKy~Jo6Q`ZA?@0!(MYK4!`xtL(49Kr(_0h7uVM0VTKEWYNiJv$crY9Y_-@zqD6I%)nnbKCHr!0NmuTL0*W zuvx~2<>axR<$D5Oh=4*Y%e(km=O;*fh&=kQL{zIPy;q$p|A4G{qKGuIZa7q=wmHeSR8WlBK~U~#^r$zypI3q zF^(;`w{f0wk7#ztv-MNU#h;jv?v|a#q7wV=rq=wq6vON?79I|C7-!Y^6s!{Lhe`K> zB1~CZg>hbb`Hc0I6TQk+&`j|g) zX_I_>>pg90W7A!rFLG~{iVDWNevcIIZ2l_!d3sZ!V@~03O^`mglx(=XI4dkeO)Jno zz+*NEGu25BfT0~)=$IQHT8ZqVj7Zsb6uu4-cnI^Tul6IEYHf>hSR3;t>YUN_>?MNB z?h}Od(1!_y2ZkK|NJl+(B_|MvhzVK4_W^SZ<<3XyIpd4~#o)g+O~lPn^p%$O_>m0O z35ggL-A?pP`90Y(I?zVT#=?hoMuy_^dvZ5a<-UF-8aeX~C?cHv1Q3`!13pR|jQrp5 z)%)Suu=UfQCp3lnY_Ve4K=kH(2^peyM%IKGGWQtDkuAe!f{aN&R4w@3Ya94G+*)Bs zUYN3GR&o)W4FO8fw)n@tLPr=~$^qt`*S%+6T6*1XmcjfBFu8EEmM+SdU$~1cp{A_O zop)m=ILefh!~wZp<{mX{r$Ji`QRbe;21VS#iEukXVJoh6G_v z7jzj+kap>=bLz+P)c_04!Ei3afH&j~c#|+tZ~IoKtGy};snrh8da9CGov$nh57UmS zslS&e`boF|YFz*|W^ea*`&6;zE90n0g|Rit5Vzv(!_N<6 zAloPw#hc2kmMun7KTQX4Jd^@UL{sTAc+0dtnDilL~3Hj06YWEs$nOAI3Vn$aKZUH zOXq0bpdlUcp`;WwhN}khQ`3iM3Nd^vWgys5`G|IhQ7>^Gnil{He&(AK8~ zOq1MGs}g-6^{+-QcE@=xm%RS5^;|w4r9fKoY%pGpYwuTLuoz#FtYWyWa4=5a*99@V^$aZ=JwX>~p|+;%lxy0p6CX6=3b`^HTq+($3)%@<(Zkq51L z?zg{4S^5T`zqVEhHpfu)@wInDkd+SSVU7gLNxpXm41!V=Sm_c8h6x$|cCKxNMfz2t zEv=?E!t7WF{4FfztK{(WIXt7mEBaS@1jZ!bnU^iT3>Ld;ldvzgv?W1<(>cIGOfS$nOBsXp(*u1nV` zr!$`lM61nDl4~f3DJw0AN{6RPp*j5D41#>A)aP`yib9-s^JsDktCpfEne6!o)wCDS zXh0S>j{lB`WtehuvWe~eo_P$j7ykV3oV{Ha(Yrc$T0-x`#XLOdl&)}-Y)Z4W{){duw2^SabDF~XD!KEN}RoD=-Net8pQ(`rzJx^!VM=%_tCBa-yo#dJo?&sH_TTmIPm9 zp@j1Ny?7#odC=Ov3*5nfMR5F|Klsfo&Fv{(B3CmV9IiA1L#> z$dr4{>7%Nr8bE@mVbKB-LTZJi(|A&OT_9(Tu{o3}g3OKTm`aM?HFLjTXD$yfg5C(+ z5SFNYFGS-BuKQ}A!{PZF3>eRXsPhj?Iy$lymz2~l%^WN^*(^7|DcKMiR(N24%x{KB z!^#f<;v(3QOij+W`Ja70mE33VO@pG^Q4ov?HhnHRIW%^S$DwEDx^v3-7CHbkY+E3$ zC4lkrS&UDp#SA+2%63|fWFBR=)%_5=TeV04VgJz4C1IUT5&)QlySnT!lwo@JRA{~q zGhmP6Blfmq^VHvVY;^Y>adv5Ydhd2($lkIqFGLRDuaH(f4ntgtb{gKR&N|$57BajU z52Hvmi3*wQ%f*tE@>+>$#b54#W`yp=r~3A1WL!N5s8POM!Ze?Y0X$v@QVdK?E+~B! zmF$o1*`k|uPqk&!_T!HN zZM(Uc^fSxCXG=ecTEJODSGz?W#^L0|<;aC5$Z1FuN8T!=CLWYc zUlJQcfr$2Xr+Uz%5;=b|GTIpb@)WT-3zzyKV%;?Wxk@ zIZWr|s;#q3R{kLL>i5YAVCgt~=GHc27g3-uyLL|KHt<}KhYL}Iv3`pmbcP|&YM@nL zZ)JYe;E)O#qxDD@Fo>?OKA=Ba>f_1%yTneeyEI<$zZ?(-$pNNY_bypgm_LjK&9iH& zK75zS$P)b73VD$b&U%fdntYEsj1RrHy_OoVzgU=v*GXnuteaas4(cG{Nxzi%;pgY) z6{m6`lWA#b(QL-O7At$zW5NUyp-5tKauL*dQj)kyrx2xR#2VYLRK|4VK;V*o$?S50 zA#16GhwG6fRSkBB57SF`b%pCa)(kOA;9MO+vr*#!!x7SwaD39j0l&KzGg9g5ImOD$ zi64{ZYGByf7ovCNL;%FD*u^#P=wyFz zzD2e(OFv6?TecGB2!<*V62u2MJT9*9Xug`O!$vw5;N`_%ppX(+J<5*=aVF;6*w_F; zM;iYj+dZg~ZEkL^w{^(r`>Fl{|Esq-m1k{gN_rXni=RVFGl%=h z?{xiR_p!!Z!H}}g1~Y@&i8u;j-{CB%BB1%x9Jn#T1JuMBy8%5oA6+b_#)D0zSC#@y zsc(%rJLe|(gKn~IGqo-aX)6|Tz)hF|tj8Mf8DSkFC<(npUi#0l^wlaavD^ib!T06AAy0Jr%jGg_`TVhTJ05S0qUa&OQ*iJsTEh?p*7Ina&*$2FsrGVe z?c42KIF8FL-=-zcFD(4r?0!1?Gsx65WGtLnXbO`?X&SZ$X%h(FL(jl4v9f|v0nRmD zTXEY%ZmB+$E6Z>xL7UdbuZmU)pkk>h_Kz%x*g&iD;rxN6V@sRiIQhL4Z1zp!IVlJS zZ#fWPuQ-!eHs2JFT^VU6=j@IAa(#nZD~n5%fp$axzI?3r<7waz7)Z48Wtcs%Xj$C01CjV-a?xQV)J>wtPWwWI#;msg=42NXNM8yQgxC;} z?TQbv+NC7wdX<@KGt4I;L7lp~uS-4)`#7Ar+RQz3E(B|i)11VVMvL1r*Cd3axPjs* zpNb9j%qtq&g)9z>r@oR7hz0i6(Q~>_|2sYw^Rfaq_|d%D?7@Cc(<|3PpvIdX`!G20 zdD)gR*g8z#^6Zl&Q+QeU0bKm;VeyE6_s%oRe%T4ejU@p2y_izPV;V&i#~2_7SO;V4 zEU&#-`-P&Wze+7TNl|E%(y0FnYg#tm{~8|N-txk=?)%7=L&d^^Iwp9Dq*1OHVUa*p zu9U_bP?+I`@cOhX0@1%fSq~A$r(@`5=ys>KiKb%zNRbIN^wj1p&M;Lm}vq23HN6OYP zFhKF##Qs%32Ke^UaEoeNiWKM4%V|*h3F+^7vtmEp`w3>h@`Vy{~>%&X(0F|Yr*Ed@Q2z*S%C#Nmr6 zJfB@_!xEgENnUH*>`6DziwoUClTnmXx`2B*wcGAkW}FA9R1Kr)bw5Si8bltdr_J~A zo4PtzKPFS&q@4(dl=UagRdl6VeI2@O$`-s;XMG zrXVNbt~o_|P7)~?#7bVntxJZ*>^8y7q$X%S(?j3*uqAZs3koTPDJM5 z$9icqX2+EME1bXgv9*^_zs*7+ya3W$kwA$Ixu=5ekEnQMIw}F(H8vcSKA!I%`sJI> z6T=51rpGKQxfnZj)v#F_UGtiTt{V#a#sMiAHB69qGa*}eA*@uatZ>`< zwIWq8S1ceT70O`d`%SoODwkLsViWjvmVlm5s>vN=o>=pn!+kAx`1CMuNv+yEnXz+Ox%xooYK( z-vXYZYZ=*H(>i8O5521ejTvu6gWm}0g|HBH$h0kbfHM40&7{Z6mh;(hoKRevg1pi} z0|qmrn)2^n#=NelIi5uY7A!80R_r`hAG2lUGcdTloB@Htbl@k|-FcjUX@q$g1shY~ne(P69=)#$dIsUSytbhYht!EoaMJ2RGUSSVw=qIOZ4 zCPC|Nphq(dy%3truXS%Iq?v^M7Wra#ZKPj^OZx`blzSf|+V2 z?>xE;ra4K7an?(BuVN^#ILU`$tH1dD@`!N%1DO%sF^mJ(Kf%w$grPC8SAsR$AJlzb zA6NURlJo+vu3Wka<_nSFliZGL!B*>ws;u&;SCBBqnXouB6EgCL$9Q)%-NM3RT++qf z{`9{rV20JbUZl>vLF8;z75j+u()4s*ggssSwy3C`U3uNu{#2p$hUdX_k&Zy&6d%Y| zggFV(AM&*G5qm$(>+5UaPVA5*;A`}tyR3$rB(0ak0>i-?UvJO@+aYNU2jZ<0BZabt zRCOtS+fI;7^bU6gy4#1h%0Z6*?UzaxpaWf1aQ}&ON}DS)tgM_XD-iRL>=(_;;$%0G zt3?-6A8vS|QI`w{`!Xufro}`7eXw3V4%>s#&dD_Lv|3Nw9yy_WZ~^Tc_@+&)m5cm5#Nr5 zp@ds(3itKma(Q)?#Lmsz=G(oMy#ym#A#`Hr7@1qQ# z$X6g@i{awkrrc+XnttC)z7yG{ivI8yLv-1=cE$A9KI88Dn&*6IOr|=)Xl*Idc+(C# zo%3p)sS3Z>MEfiB#x#njgjBHoKT<;m;By!N>zC{2H#trF5DBsdE%`Z4dN>@KY=e3@ z$*2rXK73dVGd@u36LPM@Y8)k76)QMNk^mI4?vODYrZT3~ThG^*=Y^K_z(DA{ zyu4@~D5hOydx%c4;mbwRIplMS%PX1HqSSFv=_7{SJ_`2B4)r{PU&K8gX^>k#mo5!Q zj#{U8;l(6*j$eZuEMq?X*?PR#S~xY1L4 zbJc@?%pVOgd8bpLkDz0I!69hrq79bA$T9Ca5xDZ=O}9*D1JI!mdZQxS_Ms!HvW^k+ zz)T^~O57Qy@jC#Z5F5dQOdgB` zjCP0mv#;dPL79KYgT69;*-N_3dm|1BBGsdVPje&U05AqFg0#^E=glQ{qNG@&WE^k;enOdZ@XmA(e)o)@TK}COGjkUPy)SV z71E~NzU@@YAUlU^D%#|7h8>|Te{A$`B$EPD@}ZP$_?^ILpRzF&veZ@nJCqfn7IfER zNSy`e9rxotnM*f{-V1TfWE$=N0Yak2FXl8 z01KoJKln76d!It!7gI9Yvii-W`#H?_Z}Tvt!E`6J7kun5s=M4}y@q3E^ALqg>vZW>|7nK;Mm z$j>2~!XF1nmyQXeCvV5H8hhXyo~$s0KiJ#*BfVZu>q}pbwbL9e%G#m5g<5g(w^t&$ zpTA>=7SWk1wX1QNHN9Jqd5K7i4(xs&oN=De>EA%y^WG*;kHSYb3nN60bJJ92Fj%?L z6|6of+&i)qi=_CdIjkRXh@&4-I;|iXRjTjP(uiT7WdE-Yvw3`Oo>p+2=3_C|P?g$r zX9%L>2p9OrN{eS|JP^Op)RRt|o?a&p4d|Mh&noP52LfVyk7Wp1*xJtQu<~$nYAIb| zBPV4#ik#rC>|n`k?fxh*9wA4{X?%^YOEAWR0nB9gWo6i4HZji2+FycS9iZroMaFfP zDQ)nRvEIak@ZBK#?QGK2aNc5bJ|zTs2&lW@5C>u7liHw`ICMnl>SR;Qe9Ijnlw)#y zezJ@WUP6ORg0a?1=O^b8e@i3DP+Jye-T!ozno)jT&~)Mi@yyXk+LWD%g59})3{@V_ zX}5l6TDDzy+V{)*1`PDZbUkN#*gXfGOPYg`|$t09!}|V8;AwIny|#Hcd6vep68j)Xac~`GcT&H z1>Z~@Yq->P&Cp&_Ph?#u5=jGo`Y>`lvrsjec78Yh)7o)%dWwsUh{3LcfXlY_uLXZB zk+`UQoQt(P!;#h%hHk6_sfvc}ga zr@k9pI7ZQPSxCP->sjq>c%p;JKJtPgHLKs3#qKc6aAo*mOAD{nbJ9LOeXtie}uB%LNAn?VZ<{nn3 zNyoAD8g`*sV0`m9hBi${nQ*8-v~f#% z(3=QZ8s)?SOBR>A@$5Kb^fgD%i2NzaSZ#iFUT2#FK z9k`MDG0Dj2MUvMRNFO8RCMZtn-QD)5Idx)XDxzuhlgpJ`BosuDCRkI4n(*?jWufhR zdXdB25s1O9=B5r{)d6WQFwY833(&i7{&)s(M*0bM{z|tP?0$aOUL@(ef|rM>O%21( zg(7R^&K?qv*lttU5@O=$e7z&72TZN(UTN?k=%S3;zB%Pczgb`f7pl$Wb~1(XjLk zYVQJ6#k9p?Ylxjz*c#YOz;oF|6=@RToa_6? z6N7@U;3!%=jr&rSG0jbQp_$;@suR}o2{WN3f2jV9_d52<>Qar3NnU|9Gp+$5E8H8*$KBYhj zlN%Su)y7+sf}Q}y$ZURp;Yo$+8!s<82ELzdjmQrV36+gjd(UOW?zNu%>T`XXhG0|O<-gh2!8@J?tk-%b1v}cyjOzww)usJi zVmT6yrXs4Oql~(-R2j-938fV=6<3r4*ZG9cu)r*nhV4nOLTIw_n0gF!q>aWd8)X7DHmQ56S0Pdsd4W5(Hi3_fO0# zogokspD^;VlNg7a;%7_&kg>D=#0!P$;}r5Dr7CS)-a}ItpScdv9S!K)?1Ye7BffQ= zP~dYPPj>k|oLGol`Vt>V84Jqm~&FOl7 zI90dlJqLbuY2Xi|L>?NT?VLxn@8n_-4wKv5=`drpFxGGzq_w`c=%R&bHTd&w!*i60 zi0f{!A}O~qSI53KZPBM3wE5OV><)PG(a6r9M6xVjurljiB#;F% zOa!{|hQy}8McoR!&{*gSeyBK`aNRt0_-hqa$B4J@2#n~a-d66e>7=9W z@5dY)`WBxOmNspZ$NPQrC4~N0Qe%r<&8=J3)N=kvkAY#O9E1AI!W2TL|5=(@A%!AA zp0@C<4&xtZ?1Cib8Fq7-pG97j=*&laOTU8>Tw)>Zrp>6#zT#W|ih7;4gjePx|A&mX z!AO%}2w0chQb42b~5lP-w9zJrSIMfjG!IB4|6f+p9~Hkk(CST zI@x33`)HDHhGcRI+%EDGYV8apJRwv#9#SOMArei0unU0Ohdlrx*QN3yBg z(fR!pQdgx6xx`MUadNO9Z@pWCZCB|}eV)4Xe>^W9P+z*UqEQ~vW%>Kj-V9t!U?DZN ztVM?zOB-kmF-jI{ zh_Ub1@KJ=fDFSJqQzt((#y|b7W z76P%wq0bfve?y0uTKXX}OMs2~ zVKAMen6vMtf3(HhUdWJxGns3{3pleK`i(u(i);UkxTD0cTi-q5;E{MO4#K8n=JXC9 zAIB7fCq!mF~B|)qjwGp)Q zXd#cm&)AR%0*8OjD+(6@#O!>@1ZBeO2EgqIXz~zu{?UC6w4{nk0RH3x3F_UM=fJP{ zpBadYx~=Fm+peL*0~@>NV04R5^8)jZ*VP0Rcu z{IUz@)U-y#s-QP2B=cWu3~?T3ijlr6QIO?+fb1QkLZ!LKPG(6_QC)E$@6UO+T}7eK z+WYsizzV*VKuSG7>K~x+?|}r}fXuGrd=k3gKPP|Ahz?_jVVS-or^1S$x)0}W`vR}) zGqrD5=W1>}Ax)@^JG!hLr-hE*lYP{ts(<62tT3z{vTz)x+c>IzP@Cu^zx=oMe@Ev#Svv%J=W%2o< z-)cLa4IL2tWB8puAI<)@XGumnt3uMF;6!wf^#W*QO(|*tuMc@~Z9=1BJ%Oo_c z%4z>j%9SR1f0=s$?{-jQrx{r%hI*O)wXEX6zoh~5F1skkb>F{m;WN!P2iq~uPgNOh zhz7*U(ZK-rh^QYtk=Q8Ja;(w=BhvgDO1=%Bq-T#kkd#}mh03r}P!2`hX>liak?^A;kb;swYqCLe0KOa2l%%Pl^b8$J81`LH{V!Oe;AE3myNBEoc-*|Tx zApQx0tBD-j?Z_@Jv#_e@+^=Q{>pGdfPV4FVRgeTLj|^s2>el_R@457gtZIY!#+Kh| zLZ&}fI;yaNB==~cYnv+ebL)wc;Qg$7WuZ~o$^j0*9bPwP!rkiaQTuP%zMB*h1TgBv z=elLN)zn2|XHI6Zx&tkDy9&~tl6!OXuUkOb>rFu#y|U!3?OkQUIVty_7xai8F8;Qi`)MIOgZOUpkV_v}j8LiH zjKdUy+Q-X^T5PYM=8i{Yxo5Ds7A_l<8;DxQ)=rGjeWV96Fk)8xFl$Mq@EfxSG*+4u zJeJJxJWsKMb~XOm@rR2DzgoJ4j}@U@RKEfM0`L4L6;ue`kLY14{W|9a*hI_5DY2uM z@!U2WrqvBy8aC>38$by{#vbU1J3sPP%SG`T#~awLkp6>)(sMv6*&?{fp0WzTE@8K~ zLiW>(W5Lfv?|&T=^4EWQ6r6ndEgO#8K8%ArtG}x0fd`C;tujO-Mp2bSj>qo(d1@PL< z%^p`m=50j)*}~gbN)CAYN)-N^Bod_BbB&!}(a4CFN9Nppgs5@HBve*R=6?TDS^c_7 zjJ2#_7_Ng(Z`#rQ9Ie`5;bTEE1WB(b27!Yq8FZ=S8Q|Cp9qC|J56!vzaZVj|1$I$41QyE6%gL-=10#E$2!V-@NG~tYx zlPYJ9)LoDGF`C@kNalAnDeiM$_i4F2Ohw?o-3yhYv^2b!dmKNnewndep*j)+*uDe) z#~<61^RHJ>{RHj{MUv3vR6J5xqsY-r(0KKqmCz zyUv;M8{`Vb-S=IgIWmGh5R?gCJ?%PwSQZzx?<|!wCl`4%={(U2Nl4*gHIPJSD_IRt zVy`e^T?*v%@Rwd+8NfJ_PIW^=_~~ri1K$o5^X4KpymoC6T=r5tKt~&?_^}nI@^)!T z36Ua$$M-WS(@e45V+4eRqw(!F=2w5}JG@yd_2eOyGFy~>>I7lRX=Tr}s}^Rb>?zfR zfh|t#$!{!i>Ihqy=ZTL&*;8f!SjUL=I1(=yWJroxe#Lk>o%fCzR2mpNrU`C^jeKul z48L6!^{<74h&sz9u;9BWV{B>07u3U2Oo!e`H?neOI7ffsRKvZTvoQ19e^#RAKBMr2 z2J+SeE#=uAe^uGgn%b9Kf(Z=F-^EA zLG`*di(?cBy9CR}kE9?egS$pAabOfvuKW4Wgq47~gCD26DkE&kqO~}qRNKdi>{Ii( z%zwq;%cj0V&==jfb^pv3n31j-9Ny z9hGVYQE&->93G@(l}CuRlHd~1m)u2wx7lCp4$95eg#>h( z5zR-Np_F9kH>CbnvmbSQgl~L7TQdn3MGcdc?-f?h4GDG4z=)bzrtC82?J+Mjm`CHYPp%k!aSit8aN*o2W6 z)E#C~C&m>t+~mu3nUaw^TCp5JU+SDOGP!}DMD;eJKXaR0Z!7i$PyLaDMatK%ncaDa zeUBODK!=&E4WO~0oVOk^Up@qenV4+i)X60)&h0~HtO>xJNyeKiyEVg$RV&UqUxE3@ zMzdyOMBTc>p^^0yTdlKG?GmHeEOOwi7_@0#sAT;q6Mf^{XUV1|`sG$zkF7)&!0~7Q ziLcH3Al3~neDkIYtK9(t>~b=eU&NUzN)ukcHh zxx6@~f>FhIx6(N&K70!X7msIu?Rc}FS5L~O1A0tLRYx-(O6Y`T`TEVx#y~xBC&B4! zCJVGqGX_Ie%hd+Kp`^6)PEcY-tovHML3Z#Pv3#lXG6M#`m!;Z3!dDi74 z;UCprw|3fMFcR{;W&b)6J|g=O*(-FFhN&=xDg`KUb}>bdSR9siZI-l!&iwI5ZC@<` zOYY#uXY3sR?;njh>{yWnONKoyWzZeb0e+!TDam|+v|xJmHJ?NobWOh>?TE|Jv}u{E zC8OxFL@tv#_a9q|5|Ww43o#$kQ6s^0 zgMCZdWLc2g?uoBl(9W5rt-Frl(EFy=b`_n#XO?VUdj#s(KP-e}bsaH*YRUPYjp#p- zDzV*_J;s+d$N2^%)NGJ&WtEddr5*Y#H37Hy4|o;NR6%Rr>XUPBgza7%U32aV^-9&z zU<0NjC_va7@<5w>+jqIRDeJdVfb`BC#34yY3s7jzZI3IDpM$N{h3=^C-_^ckh{3H$ z98biazig(Q)9%4BwMw&M@P{~>b-~31q#X}mX2FY#q_d6=%_|M>U|*>@++ePEmL?^{ zV@zC{=NN7}$yaL*9#*`*k3zgf7}br)AVwnb4_l>&@I_TGVuh6r2cNi(Q0gJKVWywH_C}M1G?KyJET12S z62x5~g_Ma6*`e?duNuA^{h@FnnYh=o{zA*{K`%_QpdWe_I|9XpaGyYmrj4IHW`a$g zRjyi!hIojvlzqA5>xD_SI}&vhSDi7U?m&iexZw1Q=rp^ZC>Wf z)6dz#?rSE=_ZLe$B%?`Pzrwg>k-tN^CU#A|F~0V@^zc4k=rvroukeAgQ?55i8iRX` z2Qk3~TfKF>g7JP1ul^StzYfR&6{6Duu-Q~uGr2F>eXgobjR)^~zS#r}FP>kNQcF67 zHTfH#ku!W+{?r~@C(`QLMFqrU{>gO2L)=F`BtKwt&QkG;4?*t&WLd6-jHkG6)u7h5 zg9KOkL1;8M+SdfSGAS6FJlV7&n*9TZ$lxQVS6{kSA0(FeKTmi z;gIhzd>xnh!oNDT%~nRGVO40D-ErNB4Pv6F2_fLxOiu9g;ev-rJMmubs}%H7{y9<~ zF$zo73Y(S{7Bf*ph+?QQYZgi7Sni1V%d>N)r0w@cgI_2BLyVi(;F)(^MF|Z_bbPMy zIt4fZ3uFH1ZVC_xudN{vzhUBif4Hz@-o6@EmBZ)2KlOeqo z9h1JMvA<(|v}S@9*A5u`AF}J8wz49NP5u47M%+Q3r&BsYPDCp>ZiS$)(SloRuISL2 zQbl(`%A}Y9V|k?`8RVs30)|&F8ly=QzO$x=c)k}d!4Rwhm(WjgdJF#;4T29}YwiFj zcSL^VS)Yw+4}q6*W=bsoLLRumd(LC9!K)O8IrDvu}EX=BkB%F`N-U`44lXG)HxdN_G0(x6)m0J~6YDJ~O*kP})m zH(8PB50o21*unn!hlQ(M%5RSBkM%ykHyTl(#F(V&k))D5k@B)u{`)WK`P(X6|IIR9 zqrDI$=CN-;a$qnl1&4zO?U6C0sng*u2_d`a`QGeSUR)`YiZr{#|A!LufmjkrWV?%3 zIro4i1J6@A2rMo~Ji}L=<-;Na1_hB8ph6gZP~L&CU~XQ9`Z3uyK+$-&NQ4p3(t^PZiNgO)>VG@VAtI0QZDy&#<%q&b)sj zyLflr%*-!`o6q{-mhik9z*)FkK<+L4#OA;u14w|%X>%a?oek_@!@#3qsGK3?5hHB( zImD!dt|AO;I1If(=@0suj{KMl!&^Eqf`g=kZn%B6Uj{Y%oy_PrA7KTp0Rsb!y{6_X zafmpp0q{MOWVp+kih@#rDk;zuOJ_oOl(Jw7-lT%wb zj}(6>YXdV+{~^!rNrAK|(f%5wU&8uxf`G#Ht*6b(XsjvZ&RGO+^|@v^N^}zo9>^jv zAa)UC-Sq5&>RuPZf&Z3S5(yKMkN9qR8yMcu+>{D%k?SA%ruhZo=l#u|S^u%34m0caTTsy?!)SIclFn{~fsOG(Yi zPntGlv?|YVm{PP@y#Rd^@o*D_QWwuje}2qLxn ze}lH9i(kdL@dX^RayHj2=|_MNLzpn!_@E6;K8LHDXw@sQ*Qv}och-@UmcHrZeSa$l zWo!D8+Q5j-5_9)(zX#a53+5o$nX2Kim;@4tsZwwGcB<6FQL}TJ{k2PpK7mD*erq8M znK3-dcmESVJ8ZaO;xDph?whjrB_MDYf@(iNTp57^h@joDzzU9bC}6vlff74M(YaA5 z$d?|r5)*FQrV>z^N61E}Q2%%^j%G&6ZQ|x;Z-)b)6qv0o%Eu2>hd?e;Pld%7DTdyJ zpS(g^1OJKkpx}Amysen+&E=0$!=#9aPBl*}0RWN*Y|IP|(n7dsBC%0P%R!Sle5oGe z6l%Xevc%D-+?u0lqz|)ecs=s)10_#rR%FL6dY6?qD#2}mv$3fG+bP;TAinP};}fda z`sY;$0gno1fl1CkO(}y3`x`$59D%z6v092o6-@GRvl@PUF$1QDcup|~%7m{EHZ9A_ zkMs^ln3GX3DRZQ(DPRXdH)>N!{BaW{JCLErq^4HxSa^)gcn zV0bmEiDqIRL&Dk+?UYgVGMFdYaN$LPtzPnTm~e3W?=yFWA0XX;cn@-^8m#eEaZ9bsT7o$jznF zbEA2|XiR86Ww=$xj~pt=9Pn<<-!VI!V%xDxTj~>9ZkgR_7Mi~}o^^X2m1)Jy-h8QX z2WMAq<9RI+o!twD!>|`6Gdf<&1C%MgiM%=7;a5X|vp7b8LLKGq?-k}FLA>c;Ao*6# zlt{oI<_GG?%Ys2X4O`DrXcd-V-VMJX!NISqp#vENX@6NyO{i5k7VJf`d8ACA4W7m} zd9vz?2vNuccbVI83e#O_P)_`?!)`02&2?iAoLmq7kEN?%h@)wmPXYvY5AF#P2n5&Q z5C{_7FSxr~fWzJ0-Q6u5?(XjH?%$I4`vbSPvpqdM)m7EzA6X{UQ=(OK0@tIw@sn`p z${!+A<-m=<7^j%K9-oMyJ|vN~-T^&?y(0@qWKyY<;o>Sd-X)p3 zYMZm?4-fDD^J{a3C){Fi=H>8P;QhnSD96Ro8FmE*nHEgZ;7W*egA1Q@Xh!swjY`~aKH@zZe5dsn^6ZY;~}E$yzKMZuB;o7C9oM3O9`w1ha` zzCdYOWfxZy^DdVf8JGN7oCZ+ojiJBbti}XRV;BP|9>nM$aTzsMadk^;XksB~Vc6|w zM}rlo2R-g{b+1%z6|c@y^$JF|Wx4`w65)u^nOFa=c|B-v!J|jkZi#>dUS61dg@*BX}n^kpPt#FEQqgIdsdYZigH|solZ? zfLSzVj0F8^?)F@P#^qgG?nm5#hw1C6k(r@|y0SAhsk{}FUI6XY4x^WB<^{kFr~N_9Bfi~r91M6 zsQvvR3Bc%B0E`YN@u5m;`WtiXS78D zv2z$lP|^htGg5;tj&EqEfEtlEl0LQ4R;#kNjU4PHv*P=CW(;}m>byG;& zauS0Mu?y*mMuPoG-c|k}>tP0!rhTjZTW1s5JcGhpD0;iNjrs_g>5}bjE5C_VDAD_@ z4!a>1*beybvpCfgQc4KpPl*_$*jZsGX;QwljNh);%qttuH zVhN>?{+or5$Cf#+A;aXzepFA3dw({-^u~&_8e!Lquhd7UMi$|pVCM`#j);q>Ky9ao z_3tUz_ z3X_bqTK8vFnyfjz@D$F6jX-TDl0*~?yE*1aQcN#_xx+Ps>O+pO5jPbGN zny4`9p{iK?1!U!b`REbR`G$M7R?S4DA~CpKEoIoME-rw6{P_LEDkq~kAG`O^QTKJ+ zzQC9(V6&Ece0ed7SE(Lx=+`5P@hmHjt_u84a$2D;kU5N+ z{`}Tr;#arlK_|;yU8QQv!HURNw3`YhcHl!rpuZKtl!WrzlDDN&57%Eoaq`Of9Ft70 z6O9c<^Q{T&*KS*gjJ6Fng69`6)PM)^!-tvM$Ud{B%)zMPiX&xKEh%e4e3#pTan_@K z^A2DSgt4Oz^-2HO|`rTO4=1 zU_&ixXgfdSN0pYs%#md$7X#RbiBUf++xF*CuQ^!w7^Xx2g?xrXLxRoYl6SkD<2Q}N`p++`v9u1D#Svc%L^yhfJk zOzEF6Jrj)%cGH_OqwepyQQLm!I#*XL`j++-UdI7o27cz-rxHy33}n1A%s7m)O6f}7 zlc`JVVNPubBr%@6+q&vwtfFPS;zsJ7$yhK4!nToJz2fL^W^7>|o((9X{l@;c^OClSOh;cp$$tldVe@(k|L&G7B6Adw z5wV0*Sbtt@5$9+i4qF@S?w|X_M`z7(CG2d;F`SVxSTnOq+rJ|{_dMb~YTrf|fDNo0 zpdV84=}||JStq*n_T2HBENU<;ta|pAHn={KT7U;0H19em9W$#e@?#mo$Ym*Bq$_5C z&VB^w?e<6>xe8NNGbIDo#4fXz=#X-|8c5eUiMfo7mCGUAM7-TN3k=1nlMM?fwZN9CdvjOD zr!JWV15`gnGq@=|4~04AYCnf&%*#BjfJcibs2v&gz?c{$;a{$*7^5V22N5*Z2dI@) zUl30y>{LrAy9kPQBWD}`D>^R%fpQ4LS6nS-sAGhY$U}woUVM&*$cNJ0-i6Ith}kX% zS|#^&ftho*sX$u5W63)I1Hv?)tq^h|O6po_Yz}a`kn1&`h?dBBhBq(r2esQPBw2+)4G|*y56%j9K0AiIt3)uc;(3;M-DmLUZMDXWV8?w%kufZ;1!qFckfzFvq&O@1nnX$`U^}j1-%()O1y!5zoLIbLtiTEByp;bOa554 z?v}CczkrR1in3TRE+JRF6?1@24WlN@iT^`ebl-b0CekU*@ijKYJ)Kqsr^p~1PW0=J zXlk-_O`Tw0C>bX5PdaWW|FCu+C9(|Z2p{)&xJ9y(_rU#D90Q2dt*LA@uQ4(s#M(yi|X^*50b`Py-8B_%J@Ac(fm@v>48ME5Xu0F}qs^5X9q1;3UQDznlG zm$wfp0ZiA9_!UeDYDc?~16%+6lHl?6r1@Ot(@<&-)n#N?XZF&o+Zm?tHf`wRc~@Y; z1B-ml_u@y18k+jtQjFSA*vNPmkj@v^EW3EsgfsC8XHl{hm%|5q4p<88)V^e9;fnXh6Ck>&GP>cGXTk{fyQLLWdN09GR$bV&179!7 z9<<~91sjU}QFggvwxm!9=#p8&6~nx}J|Mk^=VXnrmnFevn=Xkg8Fbr?+)6*j+)hV7aesm7k-0i%oc78irsG+l7BF!1NcM z`&RAu!$8}YyX*;n;#cSouHvGfrwa%w-Bue@~jbh z^6;dq6F8Cx9ABYorD3gWTo89;+VK+iVFFPT$M*_?M6X3=RDS6u9_A=-cKHf-$@5=3Lol#HnhZhAWlNeC4HX(l^#=|(U-nd zFpzgyf-dt-R?=k03sIgh@hby{R6O5_VLK3A74wb1=d`Qu=yFYuyxG37+gvvH6w#a{ zb87igV?Pt1TLn6)39jt}TRl#+?zm9kOUM^eC?h>~>nN0SFl9b&Wjis1GozhnsvMA| z7$IA*FGN7G0!+V8{5NH)EY3+(kTjeb6kx$9zXRtivqR+Ns|U>yTf!4Ud|-w}+Z{KD z`$+8uY_s{EhQ4Y0sxA)A`5lNvj)V-Bu%l2^n#1zK>KZ$!^F;X9B797`lk%aaqT;tY zqVB1x?N0;ATt;n|q~m${NtjM@V#Tg z=O9FT=3%-UhDmMR%7ISwj`*HFHZ>&=B@IlSp2GjD!TAUI#*@6XzybRQ5uB(c`x-U}EL7DwPKoa(w2( zSG)=N>e|L(WCm=g!v!vrb>-&-)_slj*qQESc95^+&{u=FwYxUhCb+(q&Q}+u;4F8B+C6Ue@p{zm7OK~ z!q8Qw%5T&ai8nwjL|O^q5k;zHII5e4vG>B6B*E-3-uv#MH{F% z@Zlw_^+?&9v6@j^^M;*KzRAfgSHNb}ulsHlk82 zsDd9M*?6YUpnClRJG~d^jvx=ph>+86PzliA>TXDcO~2;FTYXlG#14+WQJ zF!FApxu_mob8y@k3%rKneQ>jwVkLn*?Z=aGS3B*sMFn78cGGIGEI_txT%)w^lFHmD=Q>rY^=Wf z%H0MQ(x~58&#PS{-Jv3ka+J%#a@Mip8F+ZaW|~BIqzbAG`T3TLngHf2zUdIAgF}Pp zCZYjw^PNSKyuw13_;G+u9y8o!ME_nH*`@T>C>OQ$1|Cu0H%uJG9Ia((1HOM6=uMAk zT*;X&JcH3Z{b6TVzmfE)Cwm4jetG}Y7)X<*7c6@fHKp$1 z3^uzYbwA)78y(kSIXzoQOFedNs$MewC5m6o)-Rpy+>wt^%MTE}GVW@*hsI zt?q(+Jje{ONp~~BC$e4o!yLbbBz=C0H=+#|;lZBe7M*P&o@>#A?SjHg)v&#nTNMKg zzZ&GJ;0?h&xb4U4Ae!VA>-(obeenDlIz#6^`DrMOt_GDe0NAZL!}b=(OsNoh88@CR zR5akc7esoaf0&WMT>7qm&??MhkPqOA^-0v#mL>=2#rLTNu%X`DqaVDGo*Unt&!bc4UP;!e}J zCf|=-vN*8p*U}^OxymV8V6GnnHURI|iC?yI^53+bZXFX@V-30Cy&6YSb^(Bhvh3|> zs}sj%qteLk-;4upr7dKG*|9J#5XQT4qik{LxY6D2w9aDdh68u{BztVBrqCdr(1q8J z)aBPkX54;tBWh-I=Wq|BLz~CMb6j^^`_56*9gIS0dnC5ZpGMOC4wd=9{Cw`P8Yj^! zOLbu%d0q~7t%NM;;)a{y3k&Dr6Gj=Jv+70RAj=PFTWzTlb?}kKxa7Zf#;RPg zq+=eK^%|<3q?FeO3ElMgGWoc>)u&|Z(I3M~y4N=k$Cn&5E@^+fThhg^mj_l{qM%0xS~0x0(WGkl=LvdJ5B3r#5V~s9@lUI`=N=J5tl5d8uG(onM5nD zx)Wz|jbHdhMCKJ7Kp_2V6zU?L2jlDSNMoh6-cg8K=OrU3(}6LQUFZaFjrCV2CY4v+ z;M8yV^Y!12_J1T{m#LaR6pyG4wQSf^zniQkImC?jTCu4f1hda@s$hxj+Y_L?U$12w zO0+@GlhN>U$1a8~wY1>&YHxos23i`v1j-($BKMQ%bUuW~%#HDm>EG{a(V|)rjx-Sn z84%>v-rIuxvy5H`?;%8&?h9_9KxL$!l7$N#wqtkL&{DDW^D9!hK3At>*z)xd=iMyQ zW}`DnG7s0hJJ$14vpQofgUgXFxOsR2un%DweCCEKwTLP9uDW-nsKfaGgE$ zXv3XrgyBc)t*{)TP$}+OU5!x4`&pE))ikniWNoJtZ^@MuEEVWy&P>^Wxl#CLoEpXy ze0Dp^ugfCcq$K(wN1t&IM#f{kFP}AE|8ADMp-2ni8jX6JvXXYpU&&puppr47MTh2{LYel(j<2ZD6Kn4>tZt+MmogCpQCyXnoP}=bSt} z#L?>W7=OMV0~2c?C3m6>%AqqmL?niJ1PXW)3XP~aagS))PsR+=Kvi!s& z-JLo9K`31`WWEj-xRl4Q-djos806!^%VeU~wb74s^b(wsJQal{&q`L6xno;q7UzS; zss@@g=PEAcVz5SqMAg1rJ@uaB+z0Bojq?npTjR5ty%wLid^S4pbtMAWQ)yob(u};9C4%EsD?wlu$zd~q|=EwXycL@NU=jHrOy4nFSU)>pVI#F zSU88NIn%o8Fcz&efES>;U7G2rK{xO}^>xsOY}v{s(f^&yBpiPP;z-wahXX{+Ej+Pw2M!+9C75 zMo6mMYxwUJvwece8ET&7+8@to8IU;avTq%pG>b)C_k%n!H#kwpe}8Z84HGm#8-f6t-juZv%L70&c-;$ z2whz-Fx^!n^*#??GL>NR*m_f+EGc}7P!Oq)U1bKsMQ-L_AqpCX{6r#jA=Oj)`Auu( zc5brXqpW5pEboYY#q;}og()(1c)DLf#(sS-z#H$gY) zC(~5HcDHFQnRm&#c=jS0Bw9w^J2CcCv`gvnnYm_%Q}$t7;(IVYF6bCP7=|j>ch|)) zI=XHEJ61zkT0Fr}hp7MAzO<~IDj%;6s@DnI;w1tG1N?9>pjxz3mchJaOUls89 ziH|efq(-O7+GZ7oQ+HC6Z%k8IM1AWk-K0_MYf(hd1eHi=+LF?IglMP3?7fN0ZG3D5 zDH>+{y?mpnw&e}8wcZEcNkU2*lB*L3Tcth62f~KvIeDoX$_xC6ZyqwDYR$Zd;J|SU z^*x$$xi0J;@itNXP-$A;sgOW-U!NGPbn3Ao%cy<`mQ)q=0A$k1;|tTl5J+{zNkyP5 z8an2QE#{N69QjgDiKv~?YDeF#40RTw?d_mx3!Mf95M-1e0bB#0n;v0SU}lMdA+4B~ z{Yk&@;3?uby)(EkaEfB7U8a3B_ zZ5>L>PwBx9aDV>h*-L#5lR=}!aolU?{-uStG>rzI0tclKshBs?IpgP~;H4w^QoZQy zX9SrRv)7xrRa4N)JpLwA?v-6i+ZxV#ht|Sv8xCB!Lmr1{J9Wb%mq~5ol#P0NJ^uXX z>refRXvC(e{OTX9ahMxb!ix!d4{5E|<}8jrt$HWrNs>Ku1{v&E@{pUwR;-efMr?<< zyC0G_##kWT{F%9(R|CD$nAI_T<@(dj*M9qD9X{Q@S7M#1TThEZ5lEe@}Q zN$D^1o2b^>jJE=P5w$fuY(*<%Fg*}IdbAUwI;%4P*5CMO*v~HO=*m0(@q`8aq;Z_h zBw@SBhhqb=plqKMg-G3>sqe6f0EkaCL5w#{Ru_sB-A<%I6s8d~GAWAnN;x;ISnSll zBvv~+^65A01yld*@G;HVOBxMqY+5AQh%+aq)FZ(aWl-R#OPW@(W?#vw)~Q5jOqyzd zE#o8e!lH?+cB`1WlE;&#Iq}sKe*6LPZ~FE-T@Ld>J$)<_txIw6rG%d5q1O2d@vNEQ z{on>KgMgYObrnmmuEx4lX^e6!n#8f@HH7YHS~z-iSI|JsPieq-|ERjAORey;vEPbH zqjWvm5N!Bq&mckicXQobw0PobvsD{kx6K^(dreR|oU4oq)lcfgAji9Mw_v@dGY0qa zZ9WoQhvwDO*SSp0M}w3C?t>H+9++yH;og`i{EbWXkdiAi4x)|CGTPs=8HlyRih}f( zJ!PFF8Lf|78PbNz6k!Uj;lO~|zfq0sYa7_w0&**M%f=t`ZW~jWOB@8`n!B@Gq$auy zs9=-3G4!DtTG4&dVznl3Xj`GD!jmlO`c9iR=SfRhNKJ5}s@nI#Md2 zK%M;na}{wa6O8xA<<^Hks3Sm#!~KQf(?Gfxz?q4N<@}j!S@x;t-AqtBagbp<+OYXX zuHzV&F8EPf0=tP1x2P4m$h<{`5^Se%PAgE}OjKU-NPMGQg2LXex?<%iOserV!6}gY zEk7ey>5w5tOpr_#_4HQbORLi@-ZU*%IFJ5cwN@N}(`6_`zjiE-f!Zo_`ry!P2l`rx!xL$8lU=xB+G!t=8ubJ@*o5 z|1E;!)x5c{rAPGZpGRf|i-fG<(78SLrRS=T6QNF4!sY{%zV4I4(ky_P;vClQh#Ab( zgZi<=5X=NQ2GPtu$7rT$F?>(vx})DhEM(f2rrM=y2Mgfce5V}wPJ%3dM|4t610Kfm zKKDpJXwEIp*Y&Olc(oYpNNV-h?gehE-PZ%6-$$^dk{jM%8ff?>Mvvl>HyH)oYMswQ zc2+)~afpHOq#{*YbNik51-}*7$=@AEciTRPTy#Kt{&e4HU^jEcQ@`QiG!l?R{rX>p zh(`YMzp#DlZt6l2(CbY(a7}{hIkV*9BP}q0JYHa)29n&H3aWkD=zUQgD{r^0LaiR# zRhf=VOfWa&riOl9bLk{@4Bt_Vm6*p#^FVZHdF2Qr@sL?O7&~_aC#d>P?yPVW@Th2D zr~EWDS%nGe*40d4$KOOSTo>P#T|c_MS`+T>sda#Pm1%j(VZx98vU}DeKc>2ir|8sG zdu>sneTKaS?Yu+D17Hp(9#|Ql+Cbgd zEY+w;#Q>I(N6Ms+1LMd!&!!mUG8N?WV5Is zVcQgd4`H=%bQl@0X)+}|!w|P(z!_DcHRlQ6EIP-IF1|(yqvPqEuM%NMClYOUJvg=_ z_9lG*80amQ>HL_~!EE75EzAIUM5PQ0w zZ$2N{N%ut#jT4Jh(ia*bhGo88jI13Eo8n47Q%EKXR1Y|Ehd^m&ujbx8)dY-og*}gM zY}c-$rx&WJ2pb@~l2{Y=QUFJRATaPXqS6bC76c2?Q;F?qSfvJ0Ln*YPRb6MP5%~#*Bpg259`=)TzZFu+s5ve=bZ+XulGg zyEq|%6~0*?xUEr}uFgy0*Q3ew!F#rC4rPv{@gBP^d37#3lO1RrS-jydu1|bgv?&F+ zdFnoY8e(k&JwF}c!XaJtx!y>D;;(q)Iu)ddau{cV?7^ctzBfxHel^*@#=+HC168qC zT-*cLIWwR3QZpdGj{Hp~`OT7V|8pC0V?eCGxj%m#U(pPf<|gir(+tnd%+)~3xQ1*j ze#&iTWzNPo-YFaQ~*=fg!c;mqdIg`M#i35wGqV(VmFGYoP<`jLa=f$>7jw8RZ5 z|4CxD*Tnm;T_E+=q!Al|4XbTGvc&D;(`kDM(Zfn zs2pyHypg!Iy#H#fsKNyZ;Iq)1YWEM#mbD#k5pLr^Gk@-FmYOmW44e9PofzU1r=`4a zu1!x5BS#ABd5~1>TVF3dsA2(@ZV8qw_@#yncQAwiv%Jx#LFKV*N!7htM1^umt8a8# z(i>S6s?xk4ucl<*&YzVtci|8N1v~2V&p!$NAHeFBtFj94eiVY+8Fhb>8thD<7*D)v zycjX^SAt|2wmi&&Fj2&u7|<9a2?N>Ne!%UPX}S9=+v+x=K@rbA+DS>8d?;(Wr{VB$ zg5u&nsMYT+s@K^Z>9rciM}-(v`!8$LcO96YiusMihpK;CiB^z)IwY0ZGK222q6k6F zhoy<;>JN63nnQG798|5ACu|Y`VWBu9Z$ItULM+gzX+{Qxf7_ywAv4s@c^F}S;W$Px zPirIg`0AINhfr=eI(8j2)@EFbuq2WdYVp9l4zhUuuekp8!y`($sQcyjQV&P0zKy-t zK!K}&Enr!We;X&aF{|}tgp4Xp0je4j;XIH@R6xDB_if+W(I|7!g}^``i;S0Hw1TmE zb7s-7K`2x>_xh>^;kMg*P4)Yx1}ka+hfX%-K zzP=nIz5Cg(HrgEkFsSd>hZXFFs>}stxz$5Gf7>~dbh<9S{K2eU%)%Z9Qjf%((%B1e zxc+Nt;}fV{^!1N{5-Zu{y$Gc$R8VFma=cr_oGiGT2<&FJ4dO{zspztFm337NX7)2K zaqS#fQ6!LNWE_=Qc*;5;0wa!El^4~0bO}5aQU=>vt>?IT{jCa^lcod=2EVzTR2>Z9 z3nn;OO;`M@H!VI@5y0nXYILYY3)@BY$bu!m88$B5D$2yQd=S zRh(%1MbA=+z_}#0NTDX`NR&gXcywUVYd9Qc=yRjAftz-q;<~MC5}b1==EEl={qzy} z=vzj9g(UT1#*=m8lXiN!aqI6rhJ%+GjvV2@?Ed!Wk}{X;MNm%X%QRyv(^;#1IB@fE zwu#)k4`Ypg^LZWUuMjUgG>iCqRS_Al_&|`E(_x z!32Vf>=tm#cT zTx}Gcf)t#peZM*UB`s$A*3q)t=fLnl^i-U`+;lhM@@TNIPnCU?1umFrB4C zC2wo$6|&k4%1@lPaesCu?(#Dk&5uAaZWv7)sC4f!1oyh?!|dB@F`tU&E0%iP5GG2G1K}0mUznx{5RJJ)W1nHqO4G@vpgX$^Pd|#3) zY`{xu#AIpg$F8`qYLAWz?22mGEkcg8b=+FYUbr*-ffn((V4bR^xoEhl0xiT5L%^Gl zIpkm0y$^X-N4s0Sz><$p$sMK~L7i|xZ?WPx=UyX{jD-=W*__f$#?3tsT(c*(&khAD z5)w3T_{=ZjhdIksP3g0TkX=(^?u)cIP4#fdMk2@N(<7Q&Zan~&l@cjRVD^jpP&7R% z`-@WNCE>f0Ycv)GrFK$A1 zo)6FairYK#S`WvjC%wcYpd2O!pZZMOg#Z8|VQE}m&Xe>A6>@?_EyTQ)K`Qc(#O9l6 z3jkj`0Pr;^N5oNwLnUI%YMD=&LKGadRK)Td5snU~gntq^M6!RWx!r zX0iO?vg*;;lFMu4Mr~_HhOlbHz;SKqM|*%fx3;kRb(+9q*he$WjeE$p&>@$Yc3F9DP8QdY~Z~o6AS$BDbw*{W zQoso^fZa0GIMjk&N@^=iVjs+ctpAg-w1iC}2-ksZ>HBnv z@F&i1TCL=2Lu@@g|MO^9c6FRFd!ULNYJ3ON7!A5^h>hs=vhO%hC2CrZ*cKf{zMZgW&^f4Rs5%gkb{Ng0!uEVh83!oZJU+yqAs@1 zE@2_j>2NnG>0yklm4=~sDU%ru?J{24pqJT`B`V<3bj>KMT>Hayc}&BL*I%pSevm)6 zdG%#C^RUJXrrStgPuQk(>u=A{=Uv_27em(da-Sh$>PgG?pg$bs*_er1>eS?J)7$$a z0B$Un&?3!cV@q>;bv5-RA(jgN=9~(7@D#(*5rd5l&^<6^sJ{M{FYqKI;PVeoT`}gh&7BM`{Dz!ic zg?u;BWGq&74P4M|s(*}+D;mzlFY2q^!|vldtJw62RTP=9KhU6_@?YSLsNeh@61X%f&BF zhIZ1hB^VsW>W7;JE!PaL^*Uv$?Q!!mpjPK=QC^jvpVxjPVUe~lz=V1~IMR$8otMg5 zVYa$H3-Ft&U%JC4e3mRl-*YY;(g=<9Vh=&U)`-JN{Zos|UVv*mOpZ$2hFVxwAJ+ud zn+>)o>%ZmG`()iwbD8w0s_I?ODsKNOYuXHq`lx4ndGFEgOj&Hw zaa9+{KA%XX(zZsSmh}m0>)Dy{z1Ca)2Ug_GIYJi}Ka1#wg`u?>Xc2a@PF{b3Wn^Ej zSWPZDFe{(@Uf$eE-=dsdT8(3&eHx)DB1jI4FaXYH1#Zvl4^0QW99nIBC2(mR*HT;9 zKk=PfAIAnc?2gQj0ofFPWZ!0l*5&*p<9DqQ%IdryXyRC+eL) z;!?TmlfQn#TJD*gs2Sp$zshsgr0kTc+R0BA!`6156LGe^6S+N0c3p^D5 z-->TRFZ`rKHvM>mBIh;k66*tF`>pSIq1j}7T32g@9pG$!{*3S9AIXGTqSd}|nPGd% zo;>WAQi3u0Vp8mwS)Dyn6N)sM#&sw-?7AqUzl_2lPl{fEo`AjOcG@_}h#3Fp#11t1 z&s%_5@=YXvL~2^@CyhdFd}zTYRla2HVM)2Goia$sP1#y zZz_(M7HvXQr9q}v9k%YkjVJs(c!(N7cxIUkJLIeTi6p&-$Kqd8{Jgf?vqQC-KZ;Wk zyMe@ddtwN$s=vMn8u%Hjo->2kNh6%!%q{>k*f%egx$iD14AV9wd3V>UxGw`X*L?qmwGVU_GIUno&P;t=y5M7S+sC+&&KX6>bGI> zZ=QEOvddeKs&1$MfF4pEf=G?X4J(Bq`Y+c1f%UM3+FD{621TDyTo?L7r!qI@g5X#% z+11*M9D(&?ph#g%fM7Sc>7PO^}W#?^w!RDBwgsZptb&@avsQWmMhn?jUpN-@EhWaJKmYTfme zL%9f3jj+PjT7+Wlr#hTEqO$T_x)TUk;s8K|L{js-{d!dm;&W(rw1#joUO&C&;6+@Q=4RSAy%g7HU9?4w^_9;88wK1^#853 zGH1Q|GxdEr@#ypUdwJ~mwi+k05!IVNX9xLsbqkH#5(*@%#13oZyc8scnpcTlv!SK_ zmDau5$g9b4UjpqzzC^7IGZmD2=U!TL#K0Ruz}S$J53e|H2fQA*lY|Z&!jSjZ8@9Y~ z8_tB_2357}fJY5GUUc!GR>3V+R^wFg{0NhH>Vs1YuaMfj?-|mUeoAY^NCw_*7ouWN zTJJB?+uMA{GGL02ZN6qu4b~+Z$vdhm8&oO)Y-i8N5@t0>CM=E-lglr`+(86 zZW7qJ6dqrM%g}@ zwENHdl>L0BpA3?Yd__{5nbGpqaujppEfrW2YSfRafMF^38_vnIb)P0K@x0tUdmL^Z zu_-&t**9F@sx0D=tz57pm>lzpz(gEjBi{ed3w!HahMpCB=iBmq4w8^>#zR zVg8x`6Pk@gX+B{}n20-1XznWg4Uw_>HsgjT!4@~w=jbXEG+b!RDK0%sTqEU@iMcNF zVdF3rK#qSVdlsMZ$go@FKU8in^Jlghq#Juy@m)c->rLO+r0>jRzw0PFF zgdiNk^P)N%&;iz{R&Tn}CkjKT3R!OaH}Yq*@VyFp@w7?<1_L zt-=TvP;e8|xlBc4d=jcl3$;3i{S~8(c-s&V*TUagKaD}F2IJxc>hPWK@Tr^atb=tKXB-4%m<3zBCWwIpE zt=ckv_oq~K-+hdH>nRys-y6uZch$sMi@7q)wB86cEbq*I zD%YWeJ(>hCV#C3WL=q(ns39L{dq z!fujgHJ6WJed?p_Q^J+a;bU@w&{(`mZnYr-Kn%TKa#&!kFpr9fn614(2C%@ohMDgP(rmbmKMBt~reM!p1 ze@wTC{tmTH)`=aC-Jg-4A$Gha&zJhJj7%q^V~52L;QD(#j!JSnJGD^nBX>3qwVxi( zPS1P{s!IHPGM0yjGM>k<>NBtByKsqk%bO;?Mc{a6QLV`Y;Yzt(_q_Us949i1hApwa ze)_LR3%mB9eYHYbZeK$xp~`H{Ug!rW3L)~Z zBwBbp08}brq*L`C9DSrt2}7zr*;4TF|9heEmQ3*fQRM3)Fn#lVO(}Pm@(@S$t>Eeu z!)++%#wd73Xt1l0#+CH2sn(URK5PeasoBDrr~23=5n(G)lt`$Up9S^obe`QWLwWOC z>^VnFXBG>xS9&8=^F7wcWaSu@88^rEP&nO;KaQ=al{T+fIGRXIez;+5x#GUzL-tH4 zSsKq^clgaF4%#M`ixEgHo3KVi^JDSVgm+1O^EhOF8~p+BLPcx=qA?^nxGW7vC^q{e zPdJhy9CzZ`K~BM?ez6s9@m|`2KRZ8~*YUNpb%6~DkCx+EkE^dexvW|-wUdacSZtgo zch)AtZW`Mec`xF;vc*sQIL4-5mp93B+N}hpS`S~`e9C+OLyTJvnaa3d14!TjVIvja zKY+qzSe=NQ=#?hqZGk-GyPnh^VXoRv3-iB3{N|0@gClRGa;LGVQ-5uY!P@rwvr0H^ z5zxH#q#a{jgjEhCDdMdtX)VT%z3xSeDkxcf=Apc5soZ7?OL0QYE7BIj5@OXLx)$(? zoSQmScTvx^O5@%{xa9Lqe)I|T>`XHsMM}C|mho6u7)r1Os;jgWHbTCapL3fmTy;jH zylQ$io!+Xm01XPeY=0jj`DSwVKLw+n*|>489B2hg&j30vLX;w92zp)us~|{rfJ~dE z$ou=dhTg-lj5hs@Un! zILkcv#8rMDKY{mo!Ya9cK`|XC?w>1v#M_|MH^#JxUn(w_>wzR-EP)>Unc}+%cr}g@ zTxGr0uz1)Lc5%CYarJ@G0<8}A-8%g!6{}tILDMlnE&6^&XwC~FELEx5C=C6O*zI-! z-d5q+?Wr*5<~}$dqPYD%8%HC=Gm4Nm%%wdC1NCDdyi7#8bEP5GvxVuRE1!eKdfOK@ z@LkHjLGoa`Ogiq39LV9{$$>=izp|L%5{C}Cnx)s2ta?45N1a=o{xkj=*UpV|8tf)| z+7y6JRzCKj+&%e3sUIJ*1S(9$W-dD1)@A0`+mG>4d`H$5*x;!JEcnVa@7+Tf(@5&f zEoBI_+#iYyxSI536KRvrxYBL=acjhY!5x;Xw^)8YRH+ z1a4w;znSFzP5AXg58D9rED;D>&5#KQYYOu^(om{(;?BF{eEypHS7%DFA56Nim&qVT z9I{AU-b5Au;@I|u&M_<_XgY6qY+@d(X`BwCCGdBXzBwiuWGOr*klwrK)30xsVb;=? zhQOCLX8Y0OI+v7}LE9;9v};}05^>bI+Ss(d7*h2Gd!zjnkWxCOLFobM2Bnpf?k?%>Qefy*5RmR} z7-GmFB_)S$7`i*p48M!>FPw|R1-J9Qd%yd6)?Rz05B=(|& zOJnPAM?zy-@`WX|8RO;C?~hbGy~z%U#N( zC8rQjB%k*k2WOAPgg8jd`@t|SRh?LbMA5!pKeu|I6=b@25s^Auee|MrGz)os#C*H@u@lvcBb%$oj)PHIua-1ImEJK#J2_7 zXEG|2FSKWDPvQ@)#$}(XGGs*SR^0NCUsip3sS^!jc)V9m>@|n-5rAo+%<`3cyEZm_0(J6TuaX<@S zBz87gn3JuF!q?~$P<@z!?&8l<=E1M`u;d)hXkIUE`Wx?s9QIgp^bDyB zM`6l&+r49DMGJWU#RQJgmS$}TDE|%JK7yTe@__Vsk;6P_>RNLn@qjGj3bL<5z!SN zfjN5pdVJ#a6(Cke2qk>|A5(?5s(~NeFYf4G=#LKe-UWTF)zd46J$^Z}8BiI_7eBDA z)?1%~-|i70D_2jDUg0z2-ACNXz1V0}JIm3uFK^clhx{FtxAOB>?hUIQhnjII`oZI$ z<>C@mUuKR1=}@5c<6g1^olwBFP7kMt-pGwRze@12A=g(8IaDu)%8y1k z`FPKz{c|wluH7pYyI{iMpRZ|>CnnCiyj9n*I-Tt2zmwvP(AFoGIyW`lCBCd9Uk%*H=AJ<-Kv&(U);+pj%UbCl)VW|00GeM+B|C#*JIig*#Skde4}0oD=;F@-5j|n1oMpN^(j!N(*&7cZ zaJA#*oBk2zPn=_zsv6N6(%;KYgk1)J$G3X?2CV|N3~ZXHF^TP^URHfcfbPe1cI&~^ z?v8HK$irY&&ukf_ha~ym1uC}g`$Fe6+WpP0p9g7YD$#9F5k*E853y{|UGl3?jaJWm zFUNhHE_X7?$+60IMWd6Aa7ph4lY6(E%a)E!;eLP@icM7kv@7~pQXx6Z%(ijjm)`n} zOa@_p@kh{-5(TW)SXkD1IdpK>1SlrxGb@|&V%6-?=AAq=@tLt&fEkAto_dSNjbI*j zUu$b#3p89&ys(Y&4VYr*NlElK>+%ma^sw_m`T0r-G4W@A<#!by)KcTdV%22e z7OA8~a1<$8Ouo|nilG$_`B$NumeP0%Ia(=+Y%4VXgdN&95k!Z&3^$w&P_p5Be67D2 zEz4apVp=36u49b_?=>DKA2#G`Eu4$ix*%<+k@bU!uT0zo;hjA;%x|ozYxS)`NI99$ zFHQ>-v2+iWMNziY6mh5W)vk1}mGn-?_nGSVVT5Y#9)Q|*{+pYN{>2(P!h+>b&h3d) za(=GJ4f&-3&~ltNGE3i0vAKno4vM`~& zBJmYUN&R*I+*jk~zLRxGMr5vAVjiwjtNr0`{!l~DmaufPg3pVtgkOgkShxE1g)MG% zN913vc7mtBt!~F}b;v^d_R}M7CUe9KgpV1I7#h`+a_wN@8(j337H88NSf|=pJZYEwe+L7aE0NTz?=5c$UT^n6~g`VS6!|6KV8{sx&!D_mmSag>Eq6ysIm@Y1J-Ghu*S;}DVkcj2KXG_yYeNVgXq&(D+-m^~L9CF&epUN`62 zIaCVVPIj1+X15j4c@?@@QdF`0Qy`P4_$C*PCxZwEz_3IrDKt+d9`nu^Td7p`xW zK4A;Ynp^08KJiVjB3$u(rdqpk;d>=%Dkxg2Rep93BfsC6OueHf-5N)wN0HXK4Gn}% zlbF}`LBw0HTsn1tQ%woutn+Qn$e9K5mJl`s?$dsKEqLA18W!T1GZxYDdXb)}>>Q9O zl%CQkg*M>DRmtI(S$`=md^Gn&{&*g1^D^kQe`%5kROIC5YvW$9LTo7&j&rQI#pdpr(y2z;_-Z=Z~B^9FJ3(EqJUXM#+EQ zw|boZy~Hdhdz0V5@JioKwBiL7+FkL7Gn1~M_#AC4N&;*FN}AWi!{E<@AMJoEtfO?{ zvJx$-Dm5P*rg<3q(<7!Y@pbHMxCDD{MNkbtTI*m9^k&i@#_~TheTdM+p5Q)j{U@X; zfRm8Kg|06W&2LbTPT&8|_z1HU@8L=;FQ0ULf&H2&By$~sRyH${CUwl$8*Bp zv_JGoNI8pL8vjSU;-oI+sA;_R#AX_7f_O2!w;-sUp^gwN$E{CU2yRZJHc_MKUx zM+F}I(*k-edD!*yNHENh66vIzBODrzc{5pi_Ag!6rrrd=?NyvesJkkjsBKwjB_eFK zC$ue~Bc!g$CD;f0^~qvq)_FSTf_;(x#$~}RiXiX=+|hL*MKim`Tdt9H^7yWm-=GQi z7eiWjV2f4IQQ`+w`wc>+x+?=p6KQE0INWs1JJm1OsDE(-*+RP`cKwo!pudA9U&7#^ z**gwBR@5OsTR*JOCCN`PXI!HB%w2-GNTQ+oh74Hf)rvFR_ljqG*G@tqs2Hl+i{Bo; zU6-%64)>Sumo)PkG(^`eVA2t154Emht+V6&>}IhZLq^pV#kA_u?{>v&I@KKdZ*hWq zJGdpvIQj*4qqWZsqLml_K+g)~`I}e~bt)Q7o^@BG{9)9$yEVcMNj!`c0qtC=yME?32<#haYV`6iFd?g2NUvsXN(leO?Z(B9 zp45PYggSv?UiJ2hit}rGv2%D@p&JzQioPxEJBcVhdf5#TM0ModPavkX`Uwx%qKZ z8Sfo~AM)0sDZZ~=%(r>;R-%|k71iPGKw}Qd_3@inS~>ug#q|TF?cxm@@6k0^izr_R ze(ROok$=J!bn-83J?i~cM*)doqWR^;G97gmX$`{XEUpN#hBxT&jnZxMvlkBuD7zxL zmGr9mISI@@1>-Y4%>0Wacru{*1Ad8l54q4SrM3i9SgDK8-yzL)AGl|?mQH=sM8%QC zBEpP@JiZ80(YPBh{FHy3L%-NlwA-!`-R<>wg{%`(Yrn_R`8&>uNcnm1 z77`k6LZ=JAcmLbUa1ktIfm-pu1yYn~_+59}c581=92 z;WTd!QKvghW0)`)*x*0a?2y}L)tUTZ$Sk zIr(`|9YxPApq)}>_iw}uRmEAtW}UMOeF{%}&TJh*uqhsfi@-y+qBOQY5<|Six%C_i zhNy`C&72T_@aOmK3vOuA@G-~#!(2bdt0gHo^}~U%p)VgAKJ@h>_yh4;kSjy`B=iVp zm+Wf&xVoN%8@KUkO!mbk=JE=RzsWWaqt6jJMzizUDYEKxKOl72BJG~!xSc-E6ev+Qw%0dK(^IfF%VyeQ zJy}4+bj-k~HEo`4Mzwb_uR2K%^#bYo-*cK?*1V^})?IG`7owy#hzak9L&|7TUykT_ zQ}q%Kb6L}}cRrvEc_7kT(ZZko_t~5|cez>KM4lF!E)A8U8pzOH4|PTOLFV;nx?N&_ zzh-@Ce8V&x)GpeR!o0AKls!wacrfF=B65A-wnERDI)jbFC`G6Q=X1c2-E$3%Y1sUjC>bZsO(B|!(BI)elKF;sviFV+z)*)>My__-p0W+ zlg031tWT^2J=8B+bA||>GEg565DHJ(;Nw0d8oDGF;}b4HyYVJjCktwoGT_@%ac)h> zj#x>nGl*HXoYY%uX+hMX7H4n|R0%hRbp~wkg_T35={REacHI1R9Dr$-t$Q6VMK%j$ z?tLesRsZ%%{?v{6ye1~11i<~#;ah3rlZ8};`HOSVno&Ucz{k#mKh@h>;qKZq?!}~gOX*6uOSwrrTAm&?evciFMNkBVM4uGtX zo8_yxYeE8D#!GdVS>C!SYH>wf;OinhjKUc1$~x0^+kPXEIZ5 zeY&tMBHJAnh^xr)uf}9H2yPn8Ynxjl%FTU197JRA4vDVP>mAMcO_ORp6DIu-(bj*6 zuU-}zK|66aeVid@dE-*^<%2_SV)LHKm0F1oXVv4MVP2YmbbtiXAHN;u7VVNPW46kL zSkU38i`4v~$E2!un(8^n!YVi|s^(j@r##8K|0yrjXzS)Ri~?)XK2MqVk=yQH&+8Q9 z`StpY!Qp*DARDGffV9hjbIsrfw{b5E1x0*|5`;N5;-&$-xSBbWvHFW90a{!-Y)DGs zxp{$e3l@M#_m#w4iLqTC)OC-St*ZB5f!LL$4fsa~2AGu|aSdJ#RRJ<$RqabPX~f6gq!Mj5+2nGT3mRs=eC36YS>*X&bG5Bn)@?%N&tAEv~-{Y zH>SxRV=_+f-ooNU@a~+Q4)>4vLeF>lEUCjW_X|vGwZ_*lfVvjKt_Me)7U4V-FN4Jz z^3%dHF{{d`AhF=L@b~P>d`FGRU)Hm!q{*XY^@NmL8O7q<#5YL!MS86>EdfaPkDu_f z@;_<=ucz#=LgmvRbd8&fv-C3*TbeJQve&K!4=%Kb`lJoc9$^pkgZ!JD@*MkpEW+n~ z%zP1@uc)L^`~tOk{5|sfwEf$pzu>tcddmM47he5Tm)aU{6RH zJKWthGZRLKn1~plsO!j8wp|KwEB?zIZErdcs+<2p75An3?U(T`1%Ku#XZotti(OXQ z?G88iI@{^!gveAX_{i|^Iy`X+FWE;SPclxE0%eg_B}Oi8UA@3Y?gR<|)Kxi^z^ZQ~ z8|cI@+nX-JE{kGmMMi3d$lx6WK2EG%Lpi}w!bDvV%L$8G(j*gbMiL*5UU`E# z+VoceCRd!EZD0e$&CM!`tUxUr7Ttok^3ht z(?}Nzf_pkf$3o`q!FCDVB?uhzKU%yd?rl!@m#&{{Kv|_x?Bx%We#9*;PsJq-I-Un+ z7A8n2>sNQjk8qLpVR}GTQ!9;U;!w^5p(NuUAev@|x3y9MyVS4;Gq_USuCeP-UY9yX zVdMs6MYB3rT=ZLQYSPNZ@vk`*Byv#8w>kc5F?uq4G%YY?HL}JK^vf6s5 zkra*WyEa!>N6BH8O)cco!b_|Z`_BfKHShwNBW~tJkb$NUmPU&`iB6m2Sjv}^#v0$$ zoQ+6|q;S&~X`$)1PW-7@vUEk^cPz>CEypwCoH0me%f7on{mT3TLF{@r_scE8)tv){ zy+yFcC%)DR_>}h-KjR~8IgaZ0J!iPee_l?F=lt4B;J!|HNkbI^Pj%AR^>DA~ZJ!p# zBhM%=ubH(~x_x+L)>`?SbI;kCK!}HLa^X@ zCSvVpmw3ArqTWng(so0=*3Q=rzlRe5xvtaQ!QTspWMP=1yjN|{rH02jT_#29N{N9~3a z8*{RG#*(baO;%BSB#FAONTY47k>-5&CB=(!+J$z5Ok$yd<-S3(M?&U5@AbvG9YRJ9 zgTtx-+NafN2Kn#lrs5Mzic-nu3aTZS|YU;;R**smJ)P~>IcDUQfZB>OjRvG3#__5yg)gPA>J zi!>i{iIO&1gWKvMy~gkAhs?G+eaXy0^3S@_U0;{rln?IlzAKcW-1P(Anv}V!iLQaOr#fhr5=-o8@UvPtKDNVD_1-@;0DaQm_x|ODPY@u$HHWZ+E(?6 z4O*rRCwBlTMa`|X!TfEV4tvcr=$7HjMVJ1!M zQVF)}jM#~~n~3;|nu;*=(OB<-OfSy|c`AL6FSGAH2=jMb+hKXQNIRZc*B3lMsP>_m zF|5n;C+iH5L)rdJ(OJI;{v{Qs{`?3-fzjoI+YtVe5%SPnN}dr3rS`hJthFnT$O`~g z=)(h+D>+-h6D#SVh_fofhnGeYkqR0QBnV>Cc-y>?F0sXw3LMs<;Wqwt-;m=?^>}+9 zkPRhtA8`IvMJ0NEN36#cL7z}Cry8Ntd_YA=yCoqGQ6w}tn*131MN&t5@Mjt0!=sCs zTD}bHJ`tw*--@WVTm{@W5w8?!W$y)pWt&$esAMGc375R?)VKAs4OX*#cN6a%58jJ) zt$8)Pn>-^Q`C9@VfpA~Y91PE0(#g4~lj~w~ZFE2i>;gK5ijz!KW-<1%&#Lo!WAKtn zDP$DOf<`OFaN<%m!!|9;qk8Ab0bXmgXhCU`0nJ1TxJ6v$xA)e%&421mS9g5)#2!v7 z(nXUV8tJC=*N+J`4FVQ}DPJ#~JvRn)1crDl%H) z7Vp8KpO!mbz>AF3gL!z6+py=(FneyZz03^gfFe<=_0gwsb1t-A(pcH@g&eiY3Y_pG zfP;Azk5<-Y_nl2X)9HOFI+~J?xD7c3lf)Q)zS)g?54?rT<+uB940H#h)kXjPezi5Z(shg}LT73#)bqlVfT;z^Pd0HPX-&wR zldIP0O2n{pNE`Fbe4|LZr`^F*S97#jP@j7++|7Jar+giqG`xH<4*($ai=ALX9XMg6w!Iif-i7f{ zMy;nBeE`19J`U9{Qb+|b$6xY<2^!7*H_iX-0DGD}*~5kog&PiEe|nOXD8S#c7jpO- zTBPXt6qBYU_KsDHU48~bG?NUBEgWrWc*ot`Oa=js4zhH&V*64g>AC;H8P2tNZ4U`% zYP`5qLRYpW0+m`*PQwiDSeLY}0D$=4zY~SHAKwa&URZOH_BbHjax8woAtN;g?Zk}e zw497c{P~8(XX&@l$hmM)9U$TFKNjZ}4G29R@ew1%8>j#qrpxdQoyyX7Cb@rX!z|p=MnDi)5fa{*eTxW!~a~fcBSkd*vfRS?8*$Dkh%nNItgM^zq9+^ z$Y}X*0Uh~e3=d3q+|szMUa6?4IypWmdbaj%Cg&wxdQM4`GX|iLrbsce{Xxk;WuSF?z_Jygr+qi_yp4_*^F8{QjI0Z=lUa4mGd0<%`NZSim2KWc1ObB^ z(8+k8*fR_-ywu1I3%%02;uF&&NBvgswCXm>lwnp_z4jhP(`oM+nNq?;zzrP-oL5=y z7u;*dV^jUZDN!dqXFQ*Hf5t; z2x`*R=bn>#o#mQGH~W!y<;Yswlh)Laf!ceju5**lB$bsnf>;#V=FLe~6Bg@-KJ8Hu z$Vo1z{QS$)0VSNLj9lgc1tu#2FU>{wk<7c8=|i!w*|!Xx07-EA0m zEcJ$fe3~%+uficnTPsx-7(7we3Z0LP$aO%6TjRK==X<&fa@9p>(@7=#z0$(aO|)%HAVrUNhP~(7-$62I?W$WTiLHiSI_Y5IkY_lfj`GAVF*7DPgU*@|N3)=HbUd z`jl4fYN+Q9FcNg}x|)OVlo{nHxQ0n5r34#PA>rTzikd#)OtAd=*j92u%?+i zeXN2+rC>Tf6+Th*MzfP?(N`**G;(eb6PVti?zu_Kft$&kiq_ot$*myx?Ktkb%y>K@ zD;JkWN1encr>Ta$kEcoUQnkYF0yvI?cG%QB0E$8!li-i~e=HinNB8|Ax{oKZVjpau z?P!qX---A4OEo`G;=3cU`fHfaT*8qbH3Rr{#ghBXJ{F)t-CMf0R?g{q`>leR%-fGF zU3y}!gA7h%@1Zs>Mt!uRnb;0(C)|%G+m-*umfntmikVWh_^&kdydN9l(|JC<)|(0O z%pR`r+$LWM6VK?mV;SV2AVgx&br+60HFe1Dg9u+36^tgwjt1 zF6-l6y%BZ1Hg8;<-s8Md{mPGJ_;CAVG;O=CqHro$=5zP{ezjp)!XehlnS*ragV&nC zpYIvGH{u)ppO90L#@2`_%?19OT+(K0xlcX*eVo?-3dI&09b|{d9Nv?&HEs*$&X8}r!obT9+e zQ#wv0du}0^OZ){z2OF~K-^QL~jte}1Z(E}y<(Eie8oFG@oEK;SWL-~PFqjOUK$tab zczGkD^SRiA_Yqkpw!IX%E+g@2jDNxB3F@?^O&qFlK0QAlO`P#Smf?4+xoZ)d`NA*1J4>rO%eq zBO3Ku`SsdR_m;f~kIDm(?8+6wPp)TuS5L`tWB%@(PbLn;=1a!0?-{Kgov=?aCj8^$zX=Y}+vjh8fHf1@aVd&@a`52t@Pp0%QQNQk2d zEVJs3QFI?P^mAdjA69QH`@|Mkrbnl`tlVHnam@L32ERc}ALR`S$licB@k)ST$1l-% zxJ?wh1nxVaM?-JtE;J`(-Hq42mG9Ox2efRWIFXdb7QSveGCHxcw0Yk|o8MY41tvOb zd5GX|lPw%!?kAwUs)4KBZ)ORa0toHk>EWSGDE1x=8kchPFCq!Nmi@0QMpqZkDx!8< zdYPFMdI{8<4sZ8h4v1VY@f<{R7?UWeip987GFHWfjXJn1QdTr?(LpABks^RF#Rz`q zpCcn0!j}z(Cd0chxHD0uhsb!`>coV_P*=Lg6B!Xe8&}nCW$ZsGN`O9v?xH;_=*@%lB`8>fJmfxQwVWF`mFZ zmXwJmpn&I=?9WCX7mxaq5gYizRnRUxqgCPPD1H@=L^Kstw^$Y^rbec$wOLu0Nyycv`Ph~3tGC3#-tWn?>$_+C zM%y2%Wee=Wo#-=;qLt>^A8=6;eVnI29HYxl{#%DX);qbGVaOp4ub~#(OIn?gP~JN| zIcQcC%95yQZ_9m;+^9B(-L0_si4{v+Vj|fUp13LQj=o({W#@jKRZ@6T$>1Lw6T|y1Xkp=Hn#*G% z|9V+sGT#w*o}*|j2gY0BWBvP8o230$|C_J&pXj8E{l^D*#xB7MxFF;o&7_!~n8!~Xuezy_6dm9mS*py7UUxrnA zBa644^pb_T%=>_si4BozKbaJ$dg?Cgwqt-j?4<1uoF>(%WIQxw#9>bb`S~^%N#?Wp zLqoPh=?w&tzthU!|0nnPvsBH_!2vGJj{x=3zR#vo^v3``q0Z%zR($sAX&Mo$R!r?E z_+=zfCOYgx+A^cWlIM}Y#JHIAgE<$3xE(=Mg)za`Xc|QLZ0&F~%n&Lj(cz+CA{k)@ zUxm|O4Wj`^l|5~(x?_`!a`H_pXPzr3&8xcyQ^HfLlJy4LEw4LA`un@f1mvnt$H^RT zYcS*f{0WH|9fHV`j$R^W)+D4|6ioo=b+z~~dr{uzfG*nZX=YW)jv zgiDQcCnor#396-{J4OMGBdDTZ+XWCIL{kis#d) zHAHY!A%DB~=GR@x%sqGY&IX`C>MMWtcWt0Wd*9vOXN)En2 zX3EM((ot+bJlqX5OmmU8;B|IB(^g>?-0+Sa?nZr>yT|C#%VKz=k`vX@~A~}S4&DQnhCvA5Zm5h zh#@2xheB<0bhLbQ;KJfJ^^^d#prql3&>VOTNk+C>8v2J^Kr^3P`` zHyD^1GL!0e%!aT(3gkd8kykujuTY=(um4G4_ZW~M;2;eyB9l2Bjp?VMHrUeFvhc|j zY(1#1W*B+>Lk!pb4q$S?jRGPNn>0Du{Q1Ja?;G+iF^hlCtA^cB1!c9$MvHWl{~&-@ z)GZ~nEMJSua~3~w{HM&QV;TNtxBJYs=+Via77FymotGeuqzMnr-g1EzA8HM4e7pp8| zG4l*4m0FY3BRzDAeN2kEg`<1+!~n2ls)mz=fxyvZVM)DsJ7vQsfxO#$nR|Dd1occ} z(Ev+porw9(%bPT;R0Ss?A6wAK^wK_eYVFiI{O0EFiTC_ImW;hc;lvi3JNc3Iw{Krv zTwr-#!e73Cl|C!qFS!;@umv|l3vX3wyUj<4kVw3~+vV(Dr2{U-G{bgWorHVVW(GTs z?&BkLTV(9kT1#*p#-w{z1BAs|tsVvvS)QZM`@_DA<-jd~jEDd5#DGBKt{xVJZva;A zJ|zL!3e^f%vk!|As3|21O&Z$+vtJYSXe#tgeqr?#a2J=ftA;6qzZRuH-st8b2YY1W z6cmpKd8>3=Q>v@?)>@-@-Nx;0It#F#ZO0 z6QgHmP|3v=RCj*<-@)b5g8Y15f`#TdN*q6wA#-jW*?U5SlnLa@_}-roJM64UC9Sk^ zsh?<+>r)7d)6-3l{tTo2WYC(T&$7c=Wr(%dmPg}m=6QLy`o)heY^lSGiJPUP&wcTA z06a9ZpDBdA(Q_5JxGs#fDclok0}N~HFDOzC6uEk5kw^y5+q$%#>CDCXKKLp%F9!tUqN7Ypvn;fBr7-A8@ENznaUL@>hb#LC0JCC<16>UhL zv?%s((sMk1&Fy%qc)5ub`=)QKzF`&KrO%%C8@WXAK}Mq)$F#faq5>6|Cs|nL&5Pix z6GBV;n9W07LAtlTnFeGf&=b%#> zQ;bIvxJaBcc=_oO7!^2f1!LmfB$DcRt!*uT|2H{8b^j>jt!&Z~t)e&h7|_0}>DS5& zuAN)e1mzcOP2KrYEL|-J40YWOz*}Jd3>=NZn>3A*Xz|>{IHGdzI{a&v;4k zGoqjdYl%mETWKXo$TQC#_R8>dqA=3Ufr!c6bNu~&$!Bi%s68g!Cr*xeRjnKL^s1v_ zsd9}1tYCF~r`|qlv8U`?(FKUmNnh4oT}v~A4_z=aqOQ`sWA=Z#1B~2{*QtObZX9PY z??p%7Nmc99Jys17mbwJS@(VyK%cZu;Gos@Omn@m`YSgwALF~sy07{NMM>D1PLk>ZNFc`{`%wiRp?B-iZ;+}{rP*m z*y@|^pZU#$-C-3y3aDX28LDX(79yBkJcRi9EBY*Daclr~xBH^5?u~)*J>jqA#ZvQs zOPYoNkCzI?A87=I$b@~aG7h}AX{6{ERi?|dO^N7%Gy|118cS zCH3As&-eTO_WlPi$DtnMaNB*~*L9uer_KaJeQhcVHVOg)0;-2PnnnZ!ME3~@h(*Xi zz;D_}MZN+5ki&J%dBJhvku zxM6eep{Dw?K*G&A(ol}^agyBx1SNv{r{i; z{{;S@Paq>MgP4x);mtdx4U!eZ^;V^~3MPKkua$bpdKA0lmHNrt8?RR`eP6Iv=HAA6 zwT;g=d3Jh6J(i!B4V%FZUepTj6dXT)(!3Kjm~CfHiD{IKkB=ANA-T`TcbJBzL?qcy zsXulbd!+Xm!TC{q>bIjg&6wgdPvP>}v@`b@PG4WyE!wd`JquU!C>JYRQq^C&1$HyG zV=d3;Q@_}$^>iMpXyYz&j4!daNJ10+)t%X*Cqb?B9N-w)yvFf*|I&tvQ0g;buR1P& zp8iRBO#K((9hm9r<-@E|n8s>Y`Ny`7pj9_vU!~C(z;*RT-r%Ln*nN4I9YF#T9DXhS z>!tB21hO;SEgo-Y_`P|*rM;R6^`shdF`K4NNtBW}7I^h)&1vJ+DLSZQC? z=F-u&=NM^ryW{rN#)=!1V4y2e-R{Ba&QrZ#DF`&nv4wFE`+RtUOWoZFm<2T?-F~;8 zIcg^j_D zkGjMLSWP8Pmhio5Zd9Ae<4RLe^i{A%mw?r9_hBRN-`t2w3gF}Ae{(z2 zx!gTDPMzkUR&|IRBR#6F-KvI6Fz7*U`rj7p`~H%5FBxs5<#a%^$`3La7WI(uXmP3P z<{HFoC`fxfUkxXHy%fmDr}q+gPA=~9#3^~4mthY6FzHQRb8tAzZ}GAo_cR|I?U8t+P^u2}pj#4V|3hvD=q>t|p;i}Qkv#M(mJ1max-oJnI?j5m8 zG0pn=`oO?Ib#!WZxrnsaJV#z$p7U5KmC@6uPo6!CSzfl6cAEfOwfNR}_Jo}sZMii7 ze=luRbw2R-m+enshbi~ZG`M*$b`kn+&$2pTQu|UlA>w|2o(Z$Kj(^T#+}!P$J~0i| zxA@|zmBe(f{LJfD<30bK`4lR4+1Gv>6GFnmJx5!=Dlp3jw=P%0_L>cfRX87Ki_{$9 zR6@hIW*X{>db00Xe5zgsT@DflK2T6Qdy^A(7v#?ny5wNMaN=G0n>_ zQVua!r$&%&kJ`q6S&{{judc3|IKaDJ_i&S)R^gpM;LF7~yt}93)d#9JDuOD^pipq~ zN$XX!)RY|@Ly&-GK3;NL+L&((k}|0QRifk3_3j;nwx1M<;4D*M-c zqmintmV0524z|7hx-+xQJ{2NNL{){50CO`zkm0b&)?DkCj=INfK3Hx0xZe?_VU!^r zx2T&f$XZcNz|mK@5WdH^7lWq4A1BLg-5&#?v47$E25f(5Arr&WaI%>M!J_yC20?Q( zb|_cy-`{plUgu_9{)4PwnP*H7J|DnJPEO(RoMKW$edXVe7b3h!9)go8C@CvMIHjK2 zgrC08DqM!OdHj+c_4(9oyB4obmu7Iat3X|L#^G;UPvCzGLPwV%1r&gHZzNir$wPPz zL8_Uy&jTC?o|Sbz0b9!JrkJ64HR2Y(Y0xx?N@b2UxIK4+h)FFzNgq2AH?&V*5hFwE z(jmAnQK}ItP%O%YMAvPiye4kNyNL_`*xP2lk;&}V{H~f4j<41REjrNE2Q~Wlv}TY_9d^MO_yl@uKubMaB~ts z(Wj>rF&v^ju5A4h~;;*Q^Ke7o|9IlUH?&^r!_mY9Rl%{6-6HYF_o(=Bn z)SpiaFa?>m1xhg8GmnX-WVS~~lbGOk6`?m-)x1-Uq-h94Oy|tUilVIo?J``1?VeXM z&}9Uds_AI{$&8>It5wY$a`CaYMv`+<+NjwR`1se?AJ0~& zD&jS=NmJHVvr9O6yeBQ1GR>7;v<>VunV%`@qY@Yn1R)W~RAXMASbuyvP>)4=`HRd3S>Q>Y3kYS!-$jc@@mSXY~B! zIEFIMIubEm>>GFj=^?kxeZ0C$Zk=Mb;#aZ{{2W(^Tr)o`ivRdnC{I{_*7mo&W>4y z45EO1UxuXSOq6iwU#uU~uUk8TV`FQTe@s;i5h3`n687XfW_3`r6jp)Ch~6b%I@?m` z78kKx*^&BN)s*7#@j5X-akLrE-X7f0h)WuvJ|!sHU6sQ1N1MEH@IJ=pw&y2%Ca12@ zu$u%ApLV&^O)4!LDpp#^c+D#*ovvi&%6jC>B#Yia$<@!*8|a06*~i~?R>_Euhy4kP z*Ll~pHp*C92%8a)IfZl+z&599Ocuw=o{Rn6S>UcPZ-|cP=q;z6lwF>En`0eJ?t{lR z+$bf3U(yo2{h$}Z?Y~4qNB1cTXkL4Xgx~r~t!P3n4N{uoopMC2;Cp?{xO}(D8c9_? zdM@Fyks@Vwv5phIQiI~uozAOyHgh~(i6C`hD+5Kmrl#vVVEwz7LW>hh=Rh>9JWMK0 zyWN!D^FesK#jYq5f_HXaeBYN06`3ppkEUUJdl+sU&~h3lME4^JzdtX%AoVYePvZQv zjEav(1Pk)fQxLtbDZQAjXP_-Tmq8RR^&oMTt=qK}JRg4)=*-z0_U_MCb^N<)9k@hN zwtJ&&EVh+(vsvRf|Hx)aQI@#gv-ae2Vqc7TPLe(|(wDyWX{<{0CW*?KtUug1zp=duh`fp~^7d6B3QJNSj$ zOvY-JfzqDl`MNyFYo`zieYAzGiX`&4N?hlFK-XOWUm-~`> z<{Z;pu4K17$7D4KGvcKs{-EQ@uBbVnGq}=2_4rOoaNxhg4dlYbc7QxCS*koaJ-(M) zbg{){?6xqAy+s`~MW$1T*t%w>z7x$Q`=QTF>)lsF9)TbAdtL;>XzyIzVnYakK+KF6 zJzKYA>s`h`eDqf==kVOwpP!z3<5J|7fy4gk4v#&--(;67aSyszoWPy%knsI@Rzop6 zsvGjH9{a}s&qPH*!~VtLq)i$M#SyP#Z_6a7tUPBva55}4s%c`v1RcqbefjeBL+&He zK%*7QG3wl-dz&{X`S?<@Z}4W6ej@N!n6t^t=5#0Ze~ne#5K;Q~yF~tcw?~FqMOR}_olW#P@PY2nu{0=0bI6qO+L4;(y9}ez2k+Khyk>~1CqWedQ8K zG?P$W*Ponwq@nqa?unT8yY)pjb&<3S${4cf@WV2jrH-?04Lr6`=BEC;3|v6?KsxWl z*R<~L`yy5?KL?qb1Ef53oeG?0Oyc9E>4BY^A2(4grEbYDG#%!24XG00;23G(z3YqQ zX#iBRAAEI(MLAfy|aSu+lIhr#MXkb)f9Jpyc~g2)}vJt%P97f6%C&R~z59(CkfN<*nqNDAA_T zEs&+s($X6Dm)H`Yiuwki_y2IFlrf-6FdyapA}D!~(*4vx*~t&Csd;~CcN&c#wTO^X zIop)loNXR!e_ZNvPd8+&-UxUj%k>S@OkM_Z9d&;q%q6t9i+Q7gyss(1L0z)-<9(9M zv+Xeh)jj|z&b9g?!@5@=3$f5=5SOUwyz_RUKHJqrj3KC0rX&%v_Dfs{Ba>jJbPou(#z46y0@5u7hubs-~RBoIltSvaCW zKmCzolFqvmxpyAF8s#_2>&lm20F^#q$NFmgyhO6MzNj<|M54j>k_V_n(p=@se`%%& zpF}XMwSgX@xP#I(xQ_PiL=lY8^@gFY?YC*kSo>5~z!a0F16Nn8JEj@|BQ2+xbxX#>ua zz@EflP)|KIHU%6l+WyyQHuPX5#nal*%#784YsRU)zlCM{`I9GhBS9x)#g{R#qM-hk zD*zzyD=TyI(Q`0cdVGING9QSeI(}PrZuD=+l{*q(YC6g~2u|YD*)5<<9y2mCpZ!T9 z=L)4{7X7OX>@*dIS10zdRqHenCx|M5v2;j{Dvf<{9lvYi5e9Uzj)@A3=j{Qv;eQLm zj;1HV4*U{z;E;grzlFX(9;)~lbzjJRoT@M88$f9RtUsd#-t3~p$o`ESc(4Z*md!t& z7f)1LZLli^R*T)b)puNGb20eb-26`x3FsccUp`TodbX_Jw(-c_Oxvj)5-nrWsZC*( zx_ui>t18@q)aDMW-zl%d?uYH7Nhc2I9}=IZasX>Las2&|bB35Ig8}%;;B=1}BjWY0 zV()&|j(@%S|L%R6HS%L>(m+z1_zN+qobPJb9ITC$SqmeOFJIEz)aQ<{$+$lIrWWr3 z?75DS0=ct4L%@CwpG{JHQ^MKH@ZYnz02?KQH5B+J~0NF6(h+wL0hsd_-pQwTd_O$oc6( z8I$pBjRWc0NCDDxV02X5#KdIWNu|+2IWs^etAzrlV~p z1cUEwwkjVqwz$oMuJ|&a_%QRfS;|4bb=aZt=C3a_ekquqa@6V+P{QMy^us^3%mt^@+=x<&j zDPX;ueDy?|)A%rV7<_R$8gbOu4J>>Zk~=(b+<}H&b{H1T3p}~6uD=>R#xLHNmYNjo zT(i)HAMYQB`K7QjU<2;QyZVoR!9?im+g>Vb69?)sfu5!@&`iw+9AZdzPJ!%AHanF9ms)YZw7F1NjT@mL`7Yy3^oLJ z!FcoLiFNqtYOumYpu3gdxUov6cRg2q=&C{~qo^3wa?V%|v;$NVlMgtF#@ejS~Bml@*3{*}X z$E(#D1k5#V>fyPTN78vUcE5C9jIh1kkQ}b(=jEf<25PE6k?s^F6KL@UlG!Fy!al0d z!k@mduQ5$sLD)HQS_PkBR__TlJlirKV%j3=-M>E6c zrTT?zyHl2#w{ER2?t6l7a0UP7)l5S7U<)B-qOFrw%dnH2&T|rg^xkq!+IjqO(Q$1! z@5u-+&b$B2cXY|T-kAnsi9Za!RzmHM+_eMTGqJ(XZ-hc-G{Tg z+5c3T{WF;9GMWIoC9tO(txTxURfFNOxR>;#cs41;bGr7H%Rd!OH4c+|BWLjWRV%Fr3+(+`Sl5qXH008@ZW+ z2Gj$Qz`Ln|DiT37k8tLKjpWPl)>()+?`?fq;4=ch$PqC!x;Hj}afnN0t!SYzWFd&S zx;R#s3SS64NXb%X@S3T2LD*dG=b)JcQ~;TWmM(z-fC==YHQQ91Q`cK*^{I7d*3h2a8~$9CwWi?)rrfON--h zy*z!KD>XhHFIFFEBGjXOrr2%p*H~18TH&2*L4?i}u%2{>)vBPoW2Jg^(RQlGHE15m zA7^;)e*K1nj`Lh9dl@BAsh@;phFNJ}5;JLgYSzvlNrtJZJxDM>Q7i;umM?VAqFhFJ z_~=QmcM8))sd7(y4Zxu$;IB;WFn_Cis5SKU^~YuXYo(;5=qQIn6%duqQn!26FbbB* z=TYMi1q)*+MVokD^Iy)mRV`&bxBldZFDUd3aB&Hb$;an?4HNAZ=Ic|pQ!Ls0 zSzqd~;3% zM5FxI(0BdE`#<~9B$T`VHmbDG6}-dP@ZM{~w0j*zL2IlV&66O69u$w7mcqlja7%>& z^WR(U(<$x`@O%G!qTMW4H$a)x{xjmAsipuJfNu$iOl|!DFGu87u0yJNc@6&#svP^q zx_q0FaslZO`eb!-3pttu2 zD~E?(UNga766#swi@@R@Bu!OITiBWZtly+n!ytuZI*#M^6&~#{q&%F7cD8aX%BK%c zt8CkU%9Juy{Q)s&Hxbbrm@EH!38*z2E@B|h+E zOiKl;?n_moWHtmeUhkz?W)PUtvGMmQzBsK3C5snVSfGSbo(5A;+{j5GHz5>7jh8(q zeI~Rbu7XwdR`CKYhNivkiw0xeZ>th@sOp1xE}R6%k{rkPb!#J@9o7Q z>z*sar8+S+?T1x;V>(h|t39q@nG*G+{(UR!a5G*)Tw{@@o`u%?$CtV;f*Q+{=Qd%n z&f@R_35N#&hKRe8aui?T;=*)o0Qyh-U82=t)Sk>K5gmvgKosF!G5#RuavtWdEedT0 zmADmfjCrGb0+({IEkKM2(UN6@BgLxR8McjI&16!GrSKn8xRhG}DeFF933~lxWryA@ zL^BzPa73K%jep)aMd<9MV!DBKLIMIg9$KnYC3O#ArBph=@mOZzbmvEUC_EO$P#|03 zrg;pIq#72LUW`AM-A*t&bFKuPOp8zyEIJJUafX&BiM9wWhOKRc{`vIbE!)dJo)dC8xYQ3|7D_d3ug{4zLHwXbR*-kQGNx6s>Tjf@%Qumc#48 z$XHH0)s8AlOPQCEsRzj@pS+VmFk4mo(M%+umYQXN%zBSs`6Q!?`H_NL;U`OkX+!R2 z9<};5(_ z=%d7kc7GY-Z3-nr`M6ExLAL70K94ZkchQcZ*g(`+{GeJdYqGa#He|q2ORm!E=AGjf zP3(__P%8u}O@9nIX^y`gL2pBnyub+M_D=W}h>Fe8iQq(W)=UH2kl+~4T3m78J%c0j;Q zdI(Tz!gU&8B|e%krMjKULl8B+)Sn@4XlhpvCb`4JLid1Ao+_1-B5@3Lx3}+l3{Nyk zDTAL?Hm~JJP7Y(`m=BZd54MUddewS^I)^_dv&)Iva)aD6KzW-#TPfA6KgKfP_bkH> z#|fjDi5k|&K7>$+%#98$tUK*?^9-1!N6CwbzYMz10a_n6-Mb80Py&SmKn&F8HB8~H z_fF@AJtzljn?2eba=dL4hiz7q*zo~0|MY=V%9d*1R-!X*)o3d%ea(03LbUV`!JFi% zK3+-(!%}k&I}UM##P}%rnmQIezdD^7pB+n5%+=KQMKjl94q>QX^u5<#gZQ`0Y4JZb zB}LMvg-xP-6t|mjH=-r3&N*S~1Xpk0VfpBmb{m?J7tLjjd)}w{@*Kly>WcuzTzA1T zBNSmr@#?6E8Y|G94@JSQT}r(3f>KE9J)gCUQw5|XSJ>b0gbaImdBG=3NPY@kR$_%Z z$50VyZSL0Q*aw4#F#e#cRUT08woEPf!B-6)z8`AWZ7)uuw87si`EW*Ee>1(MY+QoO zyw(5SA9kr596wfjlMUbHvDypH1+6WJncDV6uJPDdh2$v_zi409U`arViQJ~mjeK{Uh`u?4$%GKj=N1mEpSDj?B>5G3~=rUZp>R!3QGKi=}oleHu{e98ykf zT+E!HK9t}JDu4ts6ed#@7q3GEs9!HxqM07SbHY+(sLNjXm$SwP7Frmwqu1Pa-NU4N z_NTtD!iDi0w$Laa?PxnQXBZ)Yeb=JjB{ecu;n<0GnM>sXs(3k^!vvP(7?@qhR#+@` zwltfT#|TsFf1OSExXCYK_I(}1_cv{N?DB>Wb*lrx-#=wl!PG)5>GC#2X%aB;fx{eB z9tc_htSPm@2IHPW_1{L-_|-FU_+r=Ru0&P?7^ct%WA7a*_aM|uJB7`-LPTNnEqP7V zl^EZR>w|3%uTDV?eM>j}K4g_8!eoq_dg2FVJ%7vD*c&9Y9Vz+>z)t4qbcV^3)88d& zN=^#$E7<7_*e;z&9cFT>?0HqBM_UAJ+CwaN>jhM1)~D>8#a;X(9NWC)mM`mJK5({n zuvD#v54}rm;R|(U(P<)5?69$xLJpHD5QTHuV3)z*mT&-_kP?fOS04kN1bLyva#Im6 zx7Pq+j#}M->+iz4Fv*#k7}cx6Sf7~S>$CiyV=x|WhPBp0*d{3F@y z(M_K0rU~8NKJ#U+U8I!-)nU)B0OrQrSg%kQj~&hHAuFs}kVziu##y}Wap2WCl;=WO zy}kr0D#67P-9zwrzm#{>XdISIV$s{*a9Z7_(cMg!;x;@ry^fC!Qo*szM5W?|-&oxE z{HX*RB(@!-Y{@<_bpM@K$0@YSz5;uQh*nN*mBM1;9k=+PPiNIFKB^@~-IKBopG`~Z zuk{TO2cM%f`c8rs{r=pnrYTlUVv|>8SGm%86a`U*bp&v{T??h+@RV`+@hV6Nf)2L@%>l<)U|{NB?t40 zT6)M=EUy7o)Pd?Or%llol`L;(WzE>OWl0?DXzu-+c6;cEfHi-$+iRHCH?bJX=*fbG^QUPmy?Y}=U5WRk?uW*Z}izmAe&{BS-X*8nV zmmsou0+xMVjB4A{(tX`nF;u~y)dM>vUE_r1mG}MDx{^V)sDqejMmbyc8~AUv0FNWB zh{Tj9hS(Wn@9i6X<1u|b(5$#!&d;oVfu;#JWJF2ov|cOvn@_|;xeE!IxM6_iOSr>G z1evd5KupJ7&fk*cO0z^w$vjW7d8c6uLuzW;KL7y7InHI<^%J+hp+iQ{Cvr%^cK40V z-w@`H00D5UH25k z^4jCSuLH8>p%P6})sWe@XhKarLb5s@K$=J+lH>~ zJ7@8aiS_?DA(+ndRWTw-d+?1;fV8B4SrV6m(RPo1<6LQ~`4(A6OP~xu{vrqt3`X^A zuq+Y_-&n+qzS5XRX>gsImiMlO8nBSvv*}Rcp@s6?6p_cfIpQaSIEjR+4m?g2AVeI{ z57A*Np;e|GzY@@FjqNDY~xd4aJr3;UqygI?9JwFqf8>c$WM=)|Pnd@&4dV@7@1z$FMRk{lqoS;Ch z^2zZ!xe(K}81J3uI=x_eWLv!$${`0*$4XB1c2$@5xm~clmQNGxNW(Ti)aQ5*aK48j zX0c>g zB-#yoL3$r-*al9+c@##eF8nf#N{>KW;0?7!qX#!LRd<(^?%~ZfL(_7#C}cYmd@!@I zT=$h512GED+sT#anzt8#`o#~B&t;o$(|_Nr+4r)Q6*VKNy-m%e^YY-idrRL$O{_xz z!FmsXbHtY1<%xyQQC}7}$?E>G+aQ@41ogqc0}oEUsn`WUF58C@Z5`TxdaK#6Ne4N$ zhOA&mk%bXr<1;LVmcHM$2(=i1{-oNLmbN2GV*NB*a!N_0qtp7vbC463C#m@9N16IS z&LP`t?b~=qEG+@D-BjZ0NwXjaqs5$2$lz0}lJX?*;-X?so$sNcopU{|b}&SXx~9N` z|LlC%C_{~$5r2DvC2QZ8(}}j3)BJs1NOTXdKawCjZ49dazNeKRhFn{T*RbE@0a~Fg zp>V>PInPP^SCECje|sge_l;Y*=^6&_3n*Bmvqis9qgm>R5P54MaPZtTKXmRIQXDmg z>Rp^2(~z~a5!)*Do6@C`(4MoXwE?!t#D*=;3Rsb~oLHg9Cbs8wpbgd`r-!DHg!2B< z2L9iJ%U_a0-Y}xVb99o=Z^k&&8FrdV!50CMsuvZ{y$2r++qoDLh?BVeF0I_;y_tn^}^RO z;^NR``u8=CzWac-T<8X*={u9_V)Z>3Pw&!mtV~4rTy|k7e#bqn0pJC^~FspNSv#pV|s5=Owj?rO|f(;GPoBT&n2SMUIKG2jC zR>{}{MGS%-OcvYBGEr3-kZUuy=Z4?cz~Haz1OiI)6{B z6ad^i>$Jhj*nnU%Vf>#{Glir1eP`c2(8|&B&yC`wGk3+&Y*LHXTP)ZSyT!k&IX27L z7M?XscM7Fl==BxX1%zqs@mZWUVuemB&?f5I=b_ftL?HkDW|j{=O?-$r3|C0`A4wv9 zyc=20I2^YNIli<`G7>+5gYJMG+h$Yq7@4BsDx%0&-khAr_@O_pOV%_<4TS}M5Hnb) z+xQ<2wuE}zdn{|2;14~)0_I_4SCYCkkrVZv4|Jo+tNO=uxKdGJ6m2ohq~Ob$B?$({ zz*)O*-Jk#WG&R&{C>2<7`@rAQm0L>U!{Pe6LYvQO9nJtMupH2N#;LD-_zV@eoNxlj zs%Zi9L72~jeF};)eiM1IcG`o}Q7Hm}-VU%Sn#KxXMPb$u%iYv-5& z_Fi%G6MH*!Jovcl>t`4iza|QP!a$wo!?d;tYjytqHWHVHAwX8fvS$yJCxx7FAb-UQ zKg9x3JotP>)1QD)eWgm2(|5BMD8QVe#Cx!cjQ=$gcUz)Y;yptgcQH%P%1!%|yFV0% zyZU`>hlZS|^`+j!Gg$_$W=-sNC5d%RQOE=5L<^zCE#EfOtW!1#z-~cT-F{4Ak zp&BS3$Emzkj!*C^u+Kf7-{?ukc7-X=oK)f7cTAnzV*?;q>po0 z!qCx2%z2|9!&hpVSwU7E6PAN}(BGO=>aHFqa0yp~D}JZlp{C&(;7+ThCn5_-BH zFR2i|In|0>7vG?L=qHZ-V7Cta0Bn?*KfaKig0xl3m~l#wze9iWr^do48~M;QRMrK{ z%|K2r%yDj^F+N=uI)`$q3c9i$Y(9`_N@D~iSwC`?s>6Y2Pjb<5PA$b}d9Wfg4?SM$ zJAXUFsgYp0FA2rW!bFO7YT(2_ArF|Z*;)gBr7 z%QLa0!viTJ{*BhwAx^r8XkrTS8k^-Wwgh%Q|l{+GDQ_t>$+jphc;6+ zsio<}+#djsnXn3>ZYbbW!y;1sQ?gF&au^Lrm7XNRSX~B4__mf}JCNA$?KNLNR09rtX%Y1!jqoY+hP+sQ;9Ti~{W867(fyf#`IKDz6TuL&q+$HM$aBsSAY zUn~q3&-V`}#%n&j-oy?xsqKFvYpgSd`gxl?Ps;!lX&~}w}h!<6d2#eL+y>*@MGqM+w-h! zx=YgTONwC zDGa%%)B~!}J!&atd`xn-#-b)%IPrHa;OO`$q))93QL1xXKb_!sYuOtuHgRzwrOOi> zQDgIC*nvbF)Npo|ad}GNSP~Ok7vD^)8pq zweL;QbW#+|Igc65(vZ-YtIBD9pu{vA#fHQ`+-kyG8!z{Et^t<_yN0;jPf0yy*_&TG z)N@|8^kX|iIw&D>OP{^RN%T(wuw%Bcg*=6LVlO=4i?fEW_Nwh@tNwe^08VBg>ej)N zo_dR>K+cwLeOx+t!4z)G*r_8P=xt(ifb+3y91y0?^3559@-S9*#fGp5;LU=plya&H z-%lbq)2tsy92~r0URxB`t#Y${2p^UNosA>JuFb>`wL$1EiI^P~LDK9XZHm!G@ zZ;bkI^P#Nn=YyQv0VE~oJ=rAxjRy-{)?iwGwP$c@S0>QYu>5U;B!q_744BsVY;pwm z5AC!cTWj_aoU^=c8vUn@*wJpf>uRmIfEH(1-ahxyD}b{y`k$B;&8GP{@S%AfahSBK zY~`hDSur2K^IUHqX6r?_{TJNZ(HtoDRX=5c@XGCOw$OV(3q@yAZ|gE4Bl;h+o@w^+ zWG#?PdiT}43&zL)l)BbE-c+sF;^!@lkr8CouRQ!TYETEFOIeN)O1yA%w5%b(}aPrWga!C&TN%s0|T zQou1fn&{Nuv*ZA=fe_JE<=vz9aCk#5C-%NBA#F%)dfE=Q%cOUx3gDG-Kivbp)HGF3 zz8@a}LG2-!y9)~@ffp}%3T<+E0kwk$`QP1I#bZYxVvh=Hw#5F-5537)u@ELE$r?E)u1_}$7eGAg}p*eA@+zpuTKS_-@rml(TDZEgAw^5ayxx6d9i@`<;K^UC%_ zrPW3Z|2alDw<{8TS|o0o?90g!aq4;8XzSzU+I@o=i;E@vnA0pf9H&s{QqG1y^jX6P zPnf~%_E)}|5cJ|NfDDho+xs+@>_ePzKrv%Bf`Ij{Vnt3?<2PT^(`L=Tx zPLzq3ykl}3tBOFueT+{OSt3s)nhwmvXVQvmAhhv;^G&h5tj(S7NPKJKV$*|Tcz<6J`}Q58vsp2{M1h$Ewr&NWi5eN@bE2X zTwiI|p4_;J;i}n1pwPk)wj<<*l2+!!1W;MKLRoc950{?AjSlK#CEDyeu>M>5XKX;T z{}x$Z+Go%{>s3vDxny0X8o$>m8!nqcZMEV6CwyYEj=R`ZF~dTB++YC5pfI2`JFFQ6 z^Uqx=f2JT?sNhSUE)g*YT@s7TpEBnd(x_dX+3v? zbS2|GL;z=%jP&a!r@gr^qn4(o5};(gWXYw<-!*c|XZie%O048FIS*}Fkvfn?{m?2z1zrk}PuRRLJduRSS3b*l`t@1C zc~a(q3qUDHUI%V~SdBaoC{Wcz(JdbYkj8_-vsz-a@}YwYBIz1D{8qb-vZg_!oPV`i zOqgu=hYAhyBuPG?UQk>Ia@+p>DJ$}XIP`-zWVJc{Udasa^w6kkI&_Un=y)>}nE@IK z-{B+5>;!>SS2ywsApbvT0*pPdP~DrN6*oz7AjP;jRnEYnEK>^BP4G7|27*Q?(r&dr zRsl^&G13Pn|7wWSQVSCCRm_x!QFQmf;0Pw`3M4-!WKDXLd^_kNmm(!2O!v5G+PGnh zJqq_ji(M(`n>(d;Z5mv&jPDl|n~8{5JN184;7-EGrzuxyNC5Kp)AL1ARkDw=%-a`u zSTFrLvz6}?V?*pDRz!qSEv5%A=QbgtbTs8)!jwKOF8Yt%g}}n*B#$&mR7u`G(}*eK z_G4CHCq1d?WroC+yE4(37ELKuqo@4B}@-tg|u&)Q) zR^_=euTC(kH==n!hS+8cG+b!58DGSnp0^^ga_eN-vK$awN7;S^0yTU&mf5-s$nbDw zCZ<~Now2Pz&~oOiymX(QU#AgB4RFsP8vlUM7%x{f|3)QOf2ym<8o317q7tv5KS2q( zyuABRJG``R(^nw(P#y?}eJSD(T2+<{2{O4+s{l<^=dWYVA-n48UHLT0zOu}QR zYo++RsfDGSz`cBZw%D+^qAK2*$nBSpMbW^>lC$6b^yvy*IoqQ$#a4?%{@Gm)l@2L} zo=L_eEiZ&}8ZH%5c~{8c;U+Lz6vN5a|I1qyCOd4^_F6@Py;s3V-!f*>O}u|}oP<>FZLcU0b0c;??ApzB9X0;%`_k9+Y7kIV(rq)H<%9-&`#;284(+N zVv|CA^n@dH^ba|d-Vb@hKgi3~+TMWF*KE>)deqRIB5)N_~64jDk`mY@Kne>jLI9Ii~f_lvl5=JvP*KHY(_}UFXG}z_`)^SZW zL|Y=VU3jUGBlofvt8z{t`*1Q|74DQZ0!7XbSu%&;1`D0Co+8kuOq5HwGa}im8nip_ zLWo!ryN}Ky5ZhvI1JV;Fw7rqJ>H&I$JVb(`|61IqYd;SGG)G0WX)&6O`TOdD1AMbm z2g66%dD17=E!xFSD&Hvce*Z(fPW!dxDnE6QPxPFpchKFP%1S&+i*Sn7mzp29Tknkj zqZwVOcx>iZ^bnRLP0NRWTiAR2MOKSD@TidUs-^oluka6Gp50!Q=(ZD_VSOd(&`+@S zLG|K}eF|&ab>^~ZyJe%iS=}1xy62}@ceh5AcMB_7YfFw~nUHQ9NyFShq+k2WMUySd z*Ale8-Ez94o_DLBm`7X9py0& zpt9`8x`fQKPd`kAs_0tTYsYPz%GdO8mVMpi*k3JI?0+$gC0_<&F@0v7$$7V6@2lea zQ$+*^uM0(^wOoWMFgv0&mrclzG(YWo8i^;73cYklBvki6vOY*;y#wPxt95qZ&Gtfi z7iYO&hx9oF{`~mFq<;q(@2IB`>9wHM@D(?A4bwaEj)Kdf;ms7DeBWhi7(3PN?5shlHpPJ}kEpHv_WN6To!?>W_YE zcmAo4kJrAg29zO`<3mEA9Lj>B{H0}>9c`}` ze{O9NXxnG z^6H~hmxkYolO-AhOwqn_8aGPe{n51E?LGXyf?)PpS#V7W0A`y5``%a`&jl14`)xP= z@^st%v5~Qi|4yr(&Ru5&XfrKYS&4@n@B8B-_)V*OWVGYg-zfhNm7*V=EWPLJg_3Xp zO_ZA<;(B?Vz}?h-(N3$pE7Ap~n_NkFPtB>gI3Kdp=klSD$!}cV zK4GmR?99B=hlO=WTCOyjoNq5u(4a}E8rRy#pzOsrpriu~6ab@_0umB>dwC(a>xBHI zO#~-ZtXU?Ig*T>p=pcyf8E0D#`YDU(c}sbn>+?pFFfRgWOSi5W2%nLh>DGSTsEQ9Y z#K~!xHK%}yBbyxv@o8ZE+K z;%C``>6{b*ywL!+Vn5g7cLEH+%=Ijrs#N> zdHy@doI)x5e~9|Zu&BN-T%|ii8U!h&yGu%GP?2sVhR&f|S_$b+0R^On25FE+=}yTR zy7O*+|9hXy2OmGoGjq;9Yp=c5yWaOb98Lzg0eGm@(yf<64yD1}cuSX5?*iSwz- zGHie(!6%`wwFNov0n)RZHJW?J9~ACt+k{94^sj+~b|@egdMK14tFg zoW!G73Qt|_*VCj~wSIOzNRK~%#sQdupl0|rkcUJA?w@G2RFet*nlC8@$qPDMSpb-> z!It=UjGm}6B{gCKrKNriMCCVA6N;WuDXkB6?@gb($+e*&W5G1v$y zou*^D=>q+}-8&N{mG%oF4@6pdB_;4A`GDpq?17(O4?;9EgfQGC@TVYxV-JlmPUsAz6)k^Q;};|3aqu=4fD#7Kn&6!H{J(jwTRo6JiI%TY z<%AU8;+@6TBLk%YFG~{bU)X`De*r`-b+UFgQ9*%B6v}o7#%^X0YD^%%e~~4$(lH2% zT+S??BZU&7AZ)e9o5#>N65J4?xcYAZo*k?1hd~N)1g z3&*HrI|G81aMqvoNB|`Lb?V*`^6$z)0AVSkpq++wMUS*s2W6?O_en;`y%N^L9vc1vNAMEuQ+7ZCi z2~<<<=pI0A`k>UYc1L@~*)|NOBpbj@hT$a$rq$k7^feQ$gx#n1oAdMfCF5t{ zBn|zO|0Z9n-0=7CaA1BrL7$Ptb*6z=8lx98j{~06p6Q z;4>@(mJ}{Od?@0>vP7@}*0qe4I4vPWc3g=t&iJA(Fp*GI5WzC$T%X@$F!$SY?(`F$oi_XE6NRzl?d|abMW-$A2y<^r0;N2eptVXXJFNwpz z8ub;MFXH)uiQFd#6+JZXt-0euyHDZ_fE@hx0q$6FEX&_O{A(lTFbNBQ8kg8GVG zuNEfKnL*TX?l)aw@_TTw3&=3b1|DX+S@@y@%?=Vwk}vi;1Cp-I&CN|N4pyw@YRe{8 z&XPZDT25D6s@Zs~gM*}Ob7;BlLy6|(?wZTy?Mt$sqGD)51$MVrr<0cLBVmb)+Uv_8 z+$t7bVuYCN%ONhtq$-!=unNNXaQQsI=%X{N;j#;YNb(^(#`1Kv!vo{|e^XTx0)Luz z9m~uRr?nm(YIA7m91LRSb~GJmVVOpK;nDUgB>uN>YfvC+HfOa#iDp?xhOkSiUGv~n z_vUc*fvtW)614^zwhux~W+Wh#`UBM1vvodOlHBov^ZHO=aM4i|nF!zVloBOd6q#DW zUBVJgj*6%6)t7xrBV^8M98qLGG;^PFGDoLFL$rYm@194|?Mu^@W@Xp5kskU7DY-#G zNF_d}KoeQEkG_-*LhV0$45SS%7w@2zo2+w{IXjB?K@RC>(Gc&P!I*Hq=b)Bgcn24% zEbgeOU>!2g!4pPiG_~{^&5pP|QHm-0ubI7?5gvP7=}8^T zx7T~UzIN!85g3KCOlc-ErNBhIZWgoPS{tv7zckfa3_sqt)ZI32DUZD5A9v&T~7O#17pG;|tEyE38vEMZrIW)-) z{-@qxLm0=B#>h(d$8`S-^@36Q8RZySssI_(ahwo(+VCfQtd&){i}vRWC)tr&F3?XyWtV5P)Ll{9a~^{_$Sa$%kChFPAq8&NDe<=B@offvcbK! zl`I*l3@d3Bk6XEJnuNJkgwgTDnph^ghzkWqTHakQa`M}W!gE5YKMwEqf1eK{4@#^M z9obH-J2bN2Dvk}TuE8JS&7B}h$jrj zJrHkrdEHx4ZKKEH&{=p=_~2tg4$7d8+_yAZ0;`V9S*M#^FG=*suz@kxAkrr1NsvKR z`tfUu&Lt+O@onaNBXiauag7LSeY8(L3pnxuT84ELXQNCOrb3Vf|5|^ie~6pTG>>Zr zzAO_}oV`+$#EjN%O(U|lc_1T95pnw=nX+9e8BhUEY->05XThD1+o|7NDvelbFfO=cQpH^}Y{zoB#SbJw38pcbC)!yn5u|_I&tXS?Rl(^H)*Pk>Pxv zATtAtDV$&fO{%`WKA_#=-1!R(&<^L8?nr>+#GMM8<*nLS(kofnG%--X(ETM4k}Q(> zr?$SinGdwH#jM1{#2!FV!|i|PbI*hq;XMoUZ#Sfr|8KPzHtP4r(u*_dc%4>dmw-as z$E_Vj>eqB*ZMP;`8z5`N;ATUv_azTid*P$dgurDDDTV3YLR>Az?2H$aGU zi)@;B-UoPaoU()SMT-;^v1_|yMKLb&RHQby#ICDqva&@c1lY)~)Szk7vPyB-c_yS#Mf%?;a1VO-EPR#fBS9yStPPL=F?yexqspHV^e;PC-FeYeZ{> zqCT+kkhOj=x{@{hUItlvD{N~A07^i+L(OYn4x7pOrj#rq=>KuHx-d}&1QpstXfY&R zr3g&>=N1?L{y{~`j2E0P?k(`lbDhv~+iqC&DjqUN3)VCgOHBNoWVo(c* zzjkus-UB1|Qp1+n)(FO`eO`pOm3{30HbQEYvZ!$yr=Z}JAaLe0;(KTWjX)ig@vn+B zWs(>Kz%yq0hg<64b}Tco3>hs{p@i8?;l-H>Yynnf517y1rju#kF2GI+2ni2?^bv#r z7Ba1cU8%qKY@I_4z`10dy+NV521t4x0Lj>9OTLYUIHYQ#fd>@>j`?u;QZ9lYkv?Q7 z--?RppESAe_kfQ^0^PuspdB~D0$3=4yGQzO4K#)DewN=OO%a&3qm#23;O_W>tW;!{!NT7G(SiNy+6!uZt@sc zm}(D9z#K{BQ!HoGM`MM+Cm!4z2_sPNygS+Ol&tb|avlN4ndh=292VDBIX#05w6x{~i`Q zND3%W+BMPJlQCa(JgS3AVY5~CRKM7jW6JMh3TTI^=gN9Vy_`Of&?Uc?q>NjC@3AOGH99tOZGdH@8q&lcO( z{XRRO-#jW@p89{0J=zD;zYlT5{to;H@%(RhjVeF(J-IJzDHOM!1(-;M-klFiSWMS4B#~w6|vO5o*C*gMooPfrZq@AVMv@{CWUeJH8ZlpW(45sqlrYkBp^}^gi^uG)H z?}_><@s_c7Bs6mX14#gb8i@gCm&q%sLR9Ce{~R0D!F`9VIur_ROU%FqttQP1 zKt7!DBFq9mHL1)!{x6Zlp>!&bCRS`>Uh3A_BLF(Fk3^zo@XM#cdqt!0Qx-2fz)a{) z0Sx+ZjgOiL`d5DQf?~K$)i$ z6F~>)vTm;rfvpn+KjmTj#d+m{9JGoW{Pa%6H1?~xE(iSbd5a3At*-x=ZW|cc&YVyi zCx5ip@uWnPzZw% zj1^}7#s!>riA|TU3L%0iwPZg%<-l`sQvsU{?6FBMqE0w&a3*0PwZ*LCv=lzC z_$fJj9MvM1jF$VrL;w;GF-j5WgnbZ7QCRic=|Xp}gq(K*l~Nb&mhYIK^{n;QEwDa( z;9JqTeeu_t{$oBmh6lB<{0t#7MwhxXv0|3@fmiUlbh+85i0j(S(v8)o*UrH9P0;1N zbBD!ixDlFTs$rQ3vqxRIVI%2KPI$n({dllHfteHGclJAKlh;M)@Ksc*)t+ zkur%3ZR>21yqbGQjV)L)HsZ;nWQ_mVj5`$IVd3(F->d293=j8F!(dK^_`DKpCL_mv zZ}jij6{@l|ChmO>E>}&*6a9s#qd1fW5xCPbyV@VVgph0aNP)mbduYmp^o_z&v)&fo z&cfmkz7v;B{=6y6!N!jc?DHD!{gem8NZiD z&a-(iTS=ZVm)N+hFMp4ous&j8mkgLlCpA4DPMof5C1Cyz`8@)OS&*BnFuCS|GcQK) zR6B%}Q$d@bR_A<&RXG{{nJc`-hVqM`DWZd&Om`{`o-j%$mc6(NCAR1z3M}tEHGv(> z;0%jxo!>+KZ?12$w$w+l?VLsPY3qo1{#LHxelFYQ1zN|)3?-0D|{ z0jYV^-U6oGJq=7Hd`maK`ab5LnY>v+v*mp}9^I1u)`~~T{NLvfJACq{4SS#z^!-O6 zN|Rpu@cey~)!GThXj7dcP~7$<<~2 zf}MY%AI-@_uh>@A=SZjX=!|5aXQtqbcD4C)O^4K&2G&-tR!-@-K86n$Eb3v}AMA1= zF`YlFdX}vyA95QD_@y+CpQoKG4x1^^2ne;w2>K6Xh2MRHGDSg#Wa0-JRI}G)t`35~ zQN-QIjJls^WBOp7BiafxS<8&Ah9lKf&>(>`wF?wUbuRlPL}CaTcJ9X2%nGE1R+Vdl zvkW?7oreP%;C69^0LU{by!{KKH|F%x-F+0^IsNxN@1I{E+&@#hQs5z6s2XA0mgas> zSjXPGlaUc8!{z?mNdw`>q}5f2V1@OVK76{GJl*}Lw5J@obzt|?dR4-y7haFgbmbn5 zC}qXKZvX4bMcwJm`rX0tuowR`yOZ=A zX-Wa8fGS@Zvi0GD<%haqrm?Z_ZbqNs?sRDGG!97FH}%Z6vGQama8Y$D^DmM3@NREj znx5oiqwd1YlDE2=CH*rvk@XUP77B*~S%yKappl;yCBK$vF>5^Cxy14FMtp})MYDP% zh3kSXLtu~8Dtl>x0xdZsW7ViuW9OBp95Zxp#&(GH%6cU|rD0v%cD|BscEtqF$mb7;Lb*nCQi_L5MJPHgo&1PK+iKRhx8v($(zaCuE z+rTq)B(6X_fEk@rg1TP@SSqsOCFo;E|55aXt(TGPqD_?1>eTH1AX%t=49 zLkzs@Xr(iFPii3}9m50&VDTnT1OSf$C*!mYwy`@DZ|a=lUvq4p3)Qz=AS_s3pGuP3 z=|L+eFXApba-9e9d`}kMr_@=qXxgP|HKdfhDD7zr2=9JsC}{T#ej0K1aDkWrWc_*} zbb?SE`^n3W{?;mM0*n4SGhnROAb7a!I!8yhHj;)R0Lw`D3_cflZYdtBRk#>p7qUxV zCekaXTi3zSG;}n#FV(s6aJTAeZy20vco1S^9KkId>RsQ{YdsB|;3moGv|ApocDw}J zkW{RICj^^BPG9mIlA5FVL3-Q{)nQVCwXysn2t*XNn9g<<4hgXT=#vKzB|=*KSzK4= zz8&Y7eV_r(bM`z+y<>kbQ`!A|r>kkB92qG!Tz?x`A=_v;5qm+*B>+(4LlL#Yy^evWY^U9`n!V2+n z$uq0~2D)$m&?~Hlraa)ml-%zBHZ>LO@uBHwv5ER9LI9OxLIOu-`aA-zFaDudf=Ow*g zNQr6#rLQQBy?LPQ&O0w_G_P8k(8^%dnn*j_rE1KkbNlbxOoP^V!MV28S(2{gR-LZKpNzg%SwAJox8 zppIs!O}V_pgtO=o8IRx}6@XK<{%YLc>?l0yDT)HJg0!wRud9t9M%bA!nmMugG|UWD zv0u7J2q*k?8WaXeSJA^voF#b}cXIR7RgNvfyp=^!3E895BAMy^trENKGv~-bmqZYO z&Q{rCg}@Ozm@Kb!9CFnd*EiVDQtBRmt)7^CIDKOd8ktF?jiG{9s9x|KRE?F((tDJ5z`wT?)e-=Qe zF{wGNX;5Lhi(xm&7)>(Ov1NwPPVaBqB;+`c#I&!Wi_~v&jFLMmKQ1W47wf2>PimSo zEG@ytOz;!mn+p>XLbya)*xt43ra@aFmK|A~gqoVKT{8Gryr|r_@JD}miZZ;|^$B5! z&RaFOu-(J%uAJ&6@9lVtUVutepm-_bU$A_c z(?YJ=FMo>jUr^k$r~4Q+lrgoU%GcsgalrNze+LYZ&pf1aiy-%W2w4xI_BJ{Uu*XAp zN4zjvL~!0Hife?LWujVmA2lH((2%IZkWj?~=2e+q_SXc{?sbOM2IYJNLi9lb?Y}?-b7vy^QTw7bcujfjQyzKYcJWifxCedDVJLM4P0AU~n21M%l%gUFhr|`r=WTzU zukkiUPXmwrj+&4b-psYDQ66-Pd(qb^5hpLOJuGuY6~!07pm`~^~TY{xYzR~JJ%*O^jlNw7jeE>-+a5SLbQFE9^lQW-dPMJAH_OzlDO zQ{vPR_WOuRFvREN3>i-Ql7yUg_xaG;(|xogUo`j}rh@U^7Oe(BRf{A2GtYhZ3)f+n zm+T8MW_T@Zv=~_Y%|pKTabl$9+PZ$LvDKwHTR)TigF1YHbGBpjVsN2(>RAfp+kdSe zk2GCwCBD!gtjMI?@`s7Uc96nz(rRNT7$G05|S`P3ZD;E9J-8_Z3=o`2NUa5K)^B zxBBJcCHnZN%kjLZ-#;8PLuc5(7ar-k4W5LRtvHHmN(Fye{Ulm(NH^b{c{-Q0%Bhwa zd|6VYlRWk=ZRM+(eNVVyeA$|icH2K}m;2L@ks>!k%go*9lDkJM(Lp@Xeg%nA87@cktc%!aqt9oE#{bm`9$<`7Ao7~WJrzm?$NFIMuWl>cDC_Xi z?56u0yT*u&cjN9nu?R>=USp@Q6ss};%$q&|GgA89)2WFBx9`kthxf|P3q1|u zS)g|cs{7?vVXc=eaC_jtDHctoxsGv|5@%7cqhzQminAkuH!$fRWfwv@ujS5PRu0+k zu^Z4O+oE@Xku3ksUNhqBX|?0|fTWz0x%dhEv;NJ+r@24n121U@ zeZ%^Bx}WeCc+S{yfi{MXzubIxuja8<`XuGqd6LBk_ZXdL#aMvorBVS(>$-nvz{8 z4b{0II8wi9dhW<#1kCGhz~svD=(#NaZ8DKz6(8>zIl9$Bs+CI~I&lJS-BekIy~>^O zOhBz_Y5&x2xtb!w!7Zguk=K3keeO5eFeXpSYKKbODn9EbGC!f)%%5{~(%}p4X|YUo zDGlGA%wNVamUIi`*h?LQjQd)4`%|6_(c*9(hE&>@^UVbw-Gie!duxYH$JtW5^QwC# zI;Sg|V?P58O!YvkO#xy8YH{KubU_-rJl-lj$hRlg{sMG{lFXQ5L0$Al+0byF5valGg^zV-@OFWYUx~?6EY@ zhR38H&3A)gqYZA7CG;c{!OlYSgiN>NnB46v4(X&wC9RcHSk{X3{|Xn#3C^K{=XTPl zvWL^Vx@Hn5tzvG_iRPT2cIc~Wq^&_5cH-<`5(zG-;p2_v{9^Whbdyldgn`iy~N=W4}QoY+Q*hFkk`NbD$xUUQ4 z!FRy&m6yl*RKRRn6mDi^&olJCCfH}JeKodz4}tbZoPnbVchn3fE?F!=yf5&0)YV&6 z{e3F_(;cGkkleqa9Bu~LSm$=VdwF(bq6d8X?vtI9X`+9g)kS!uR_zi{HGA%AEP^)aV;dy1xaGC%Jr#R0(G`W2(Wuu?4hs z^gXyDHJUE0M@^|)C9FH_7$WK)Ed!yY(d9uHZhty)YOEk!3Q}kIA26QJ3n=(pvWqOg zc`MCrVee0i@-`S?pDV732EApBYwM4k0s<(gMaGrC`Xq>9Dv%ND=z&T}W7%U9=b zU+JRlWNo+a>zkoV$;}bE@B9ec&Ke`K2K>%C5}h)2UCkh2R>`m!Vp+U?0lQd8d735; zXm-Co1ovCxSxFPEXe?INd{jT54r-x|Sf$vnUqh`9ELwU}udPEwdIv{lXWG(IU+K_O zVQu0=Gi=T->b!H8<-@y)>cioGPkAdLy^7}(`okWHkR|B|DX_!}GHV6Q#;qylRrsg1 zE>DKVSMMF?O_J&P`=2-{)4EZht;1etRtM$iv=v@LQ{g=?nFr4bXs?C+waPVb($aYe zC55*+);BdN>3U^0bjQ3NSSSqUAON{M$#14$KAfWNzxN|RDr=eujMSWyc-5N=eWj7C zjS+}lU~d%iX&*7g7xsd=>&{W1W=Q1KU%r19q&cNGk2ZeZP!R`O;$JXYV*36Ro0E+k ziV6=m66f4~`FD9X^-OS@vAT0rJ?(w(4ON+oIO5q;CG$Fj-nrE19xn7leaqbF%kihB z^_wWDO^d!paZfd456-BkgHxlHYDg>>8r-95V!7(!MyEW=Fd{~ftMU=Xsw->O7YmDR5U-6$~-`q*sORK+i4@>hm2LRf-wvLLn> zgZ>$BjxXm)4=>M0%x-HLH67QE4=}k#jUC&wQ@4k>b9SwEo5o8z9dY0Sc$e(6Zwwp@ zILel4pSF5#O&cGF6n1iaZw1!Se?Pt?_}cS1F*oaz0Xs+O$vDoqomcyTxGso*Vrx;;^KRU8?e>1%u9kFnPq21QY+ecHhL)htjj+!jV_Z}&{PxZLwUzM z>34^D#N78?6XJ>{Ne&Ta`mIRHT``!$+!JPI=IMF}dad2k zm%o3V;q0>x_VCWtZ|MhnVb$t;+;)A|pXt5SdJ;PQ!&jJS`)!lfgtws2?%Vy`6{Qc> z>`yl?>kljAE1j;f&Sff!``!MdW$<}{W#Tp^B!F6RoLBLR_DW_rv#L^FyRcppd>Isr z#}z5GuLAF=YJu~58>-ulzuEXb^WF8%)oA~o8e`F)7K&fVW3DA^fMfr^Ih zu2zd)ECu^z;=ieev5jpzh}C@T?^on9JDl@4Kp3SD-}A7tj^}xjyvEs$h%iGl88^8t zr7dw}d)2g42EfCc#+ns!zTp>BqY{kX@xXm!bY zh1Xjv7f8SD^#%P%BzH0eQ}>Xu!VGuEjz_s7*UHdg?H^mSUV-Id9l|hd>er1RN%=Jz zYBylNHTBPtYSAHbW>SEI>2!*5_}X(BVYJfpjV5oL%6RZ5 z!()D>9x;-f?;e9EuNZxo9auJpeVA`FZ-y%MOP8vAd*gW3v4OYe{x3?wZD~9a{{paY zk3HtOne%~eOx|DDcAQ?EBFC2^Vc|7jX%#L+cwM7K0(lykYkt8^=4zRPxh$_->}iam zx3(U5p4du0eQOf<>G7*g!kY3Yy$y2%MMzDPxrU#xUI!saIgBy+H+vger(Q8XMPr?$ z6&&++yW8t|?t+t|$nv7qlHbN2x5d=>Bkq?qf2LQawIej^Tprf8k7MS3-FkERw(okZ zw=9_s{N$gkU6JuxP1eecj(Wa4TB=&q-$c$G8f|ZKk zaiNp#uD6msgfhd?jqfuSskTgma!%OB6(Nrq#Kb){ zU23!#I{gmE5cPLAtBAMY!D9Q|)?*vQzuCrKzE=b5;pC(1Wn> zx+Z3Ss1IJSN&DS8Gw%=sm3eD{w2fNw>r=k6kXj)ZSsFU1B*rPuncqUJwYQhqrdhkg zCII~Pna0&({5XhA)QxK0J+sl*tClWrsf0{`k2^&T5H?q*2PXDwcD) z@ioiPyrYnq-B1#0{lC;>E}K5|$(!Va^^f{4|Cl|tBbIX1%AUG!-{IbQA1| zEXL8n2Bwfo;0PgMJ9T4*%Mo^-bqmvMt^bjfIfn)llqF?88jC5Jh!wKQ%;|1B`>=AZ zg5@myJ=FL1MMn#cuCv9L`8srIbj{p7B~##qIcab3sa4YDIZ0WniQSq{j*BWyjO3!@ zv)S4Rdp!N(-q~OI6`C@uLVRU%_AWOo?o+uon*tM6u9UT$opzl1q5dsCsFMyxSTr=O z{Q*Txpj&rbBy5#?ty}BDd(V{t-nk7K2Zfp$aEp-)?Bx&EZgl@!;gUa$R{2W0>G9c! z6*tCgLyzml25p{d24}~TP2;fd*9DtVhRU^n)$5fo$04nYv9%)Onb4WZ+VSzH`sdYS zj`yv8q0J;S#Y%VY=4z-->peTAaS-uAF@{a3T87-HWxD+M^}h;WWHiHGRIQgw+$nWl zKg505wOtLdeQ*J)EmLd&iy=vviu9>7#mec<%wu}|-LP5R77Ogi^JH!EQbHN; zmDDhQbKFfAbeR&tq0a1VAtI$o-}jsC1T?z`zk1E)mw7YNQ*j$-VN~D(^8q09gxXsv z-XvxlKWZk&48H|usQQQy_iRY_{1K1!TiV>bjx18x2=|DX20_BQN&4{_i^ixB%D`{b zCVdmULe7nr&vh2_Ml~(&BheRgG@P%YnkxCSLvdd}1{I7?zN+5a2-vgnJ45?BBpk9% zve9@D)wfamyThDR`L&lWf+TC`x4gRsI?8MfB*NSNmYbvXz=~DK8I(5609&Ale>@l7 zi1%-7kUX0Ag?>zP#^msjW!l;M=_o!xyQI%Qn)$jln+nZ`w6wqnZAT$y<+c6nZ|KE| zww$d_{#AL>d0#slFSu` zGlkoQTQjv(l@GiH)A8*4nqyae`{NP80Tiba|+?6}Ru=~zpp`_|zG zsVOoKyG>d_N#V^@E%JQ2j!QE>0GR#&Vo1biqEvr7-RZB|aI)xUjy$2~86O+n{)7;w zGCi_hNGGl)AO;YE)AP3Y^Y);uADcVPD#h19T}|rQm7Ih7hFBjGv=Y|7aqe{;;Vx;} z?JgDZMyIKd&HK50{N~0jr8?682!nrrfc9nQ$$h*GsowIrb;oqzL-sbg*$UL;+V~LI zcXo5}ca6)|@jUjL%j_h6plJE~{VfIc96Fxmt^G`|$L)ZBeuq|cW5*P)#qxJ1-tmrx zRGnPzim0lG{hOET^tG7m=H?H~Y~{JsyVyC*WSVPI*Oyy5HBD24Sm#Ro201^&9uLjY zS~m$I?OLX*+UhJr&D|+pa86w2)mRKj-|TkN(lCvDchvGZ) zq{P(SiN?)V)mj{RVU7%-6?(Zk*zh!Ld)(*i984(~Gb0d9Q)cj-vDgVVdjR5cEXQN|Oehs&$VH20j2T^^R?%X}%z#AcY){+jqUcW; z7CuUMspq)%6 zY5J;lSZFPQ`vT#%xqL#@`^oRuUXjD!3STd`uA@ZCO5?-X9|-SAcO5B{`{A&BPiRST zb&D$VhSK5>Pdy)jO&zL(WH-M3EC|*8`HzP&NZf0wL`Mcf?f^@s;^5@Wc27ArO%SDFt;8vdNb<}L4%?m2;ag376X(`lV%(UXSFpn9Bx9<68=&*f}9i@6=u5p?JNjGfLaJmS5KI(TSwqrSHQWwbFbDAM)o4eDF9YJAAcWG(ge@+%}oA=r8fD`4sj-@2fmv z0vlA0x~>zo>~mU=uia%po7C-@ ztwocUSFTin9CqlrD)ui53I${o-$e?m{*8n0EWaVX`NT}FZILxV>S6@j=)K7F?AKoZ z7{*~0Fb;i-6X7CJ{ME+nB<4qVKY5_Q*O)1`fDP z*bXBekGvz1tE4y6&x#>eucN~GfQW+O4~!q7;UOlsz|-`_%|cL^nd>t3>1t7v4>zf5 znM&ZNDrC_ALc4_^LWApYPUfoF|Hi?-A(y^1518XDJ9dT77?tfzp;taf;DWN8GN0rZUr0BUcqtAYeCq0;U~LaC^7TkE-ZJOFO-&Bkl}dqqZz&5<6$N zZ_ek`-YN?ehsGoLSNeABSU=F_=5k%EP>AaLxO9i^bA#E1X04_BAAy7fL|qle+XYTC z4Pvv2jZ4k^@5e^cQKd*Ya1p$s&n;MBLjKyz+5&g?Qln{X*?dF4mD5mgjG}OJs*#qI zT6CShV7+;36HRB(TceTrCy#VO@*LIF9bDsP+0tDvaobj+S@8Hd)$F;D>)`pxi@ew0 znTNRSm$y?Y57;du?1!I<;er7>*dVCVU#&#ipOw&PYFcpg;7bsZZ%@34yYA3u;>bvw zV!mpS>SlU0+dTbDhoQ1P*K7`3(0IF1hiSK(%0MUbjz4NdFV8N{(Kcs5}l?!)+qJb8hhMYQ3?2+DhcN8VFyg%Ee(vRk_CrE zO|6#KNosw_OMkrYZ6q146w`#t+}9r8lPjTkUM%~JCRin@+&l`ZnQ9-lrhF~=i8cQP z9i5XJNYqcF9n5IgA=>)Mleb(sb6Wv+xvI@tWRv;%S-47#x4k z2}UjP>jb_jef4shKoCuwZEe2kjkj_ZAI|NSs}$5i>S-d+UUp+i@~c>!zSXA zDckl*yQWHyZ4nnwY$$v>s%*|Z-*I2!DQPkaZfqpp)76rYaZM_+QQ?cH%T%3-li zwT8a);#-fc!}AKieDRpD?77c!4lA(3shkhTXYCH!mYV59&qc6k zL>AqF(79Bi5)DxAMnQ8zXEI{JBbKqMs-Rj;qWf{%R`Q&nK5f{^Md<$!^%ZP+HNld> z-QC?GxDyEO?(XjH?ykWd0t9ymZo%E%HMl$M$+vs&{(<+I_e{@Bb$3;DHsI=1Uv0Ew zX7Fe>uoihIR@zYr&--XIST5^)Jv+}^#Z8KV0VO}rx~H75)rTvz$ifMgObOqMLlrOh z*_D%+spQPJ(V|{zwT76IVsyH=q4C=bP0zy?SI^U!hr@m)a<=~O2neJkz@Kbft)#fz zOEc#;!MG^X8l#=B+nK~v{aEiX{`tE`6v~}dP}R%~Qs{Q2H|7X*TaL0{slLx7q?s(& z^+F|pW(Ys-Gs9q*D5aX?@)5YsSbC3C7rpoWcq{zmojT}#sJF?-6&Dx(d$*Vu)`^bN zRCl4cCL2qEbRGt%N0P%5R#akgE{;uBp0OKVWq>%db+|z!(>4fdGN3f|$XA z{d)hLjpZK`*twN^3e<8*wh?vX|k7{zm z#J669VFJ1khQBzrYOF1Kay^s@JG@91IfjgUVV{btUlqk3=eWOE0qF#s#39V(`@&>- zukPUTb{5<9g$)hwnG;3-v|l|eA#IO6*BIQ8q;20hE)}ZYBIX|EGq2P+4&4OUGB~j$ zZn4M^tC;1AKYzV7x!r-O=s)Mo$e&$+Vf|g@9v_#^WyhrFV{5h0EKBL#{Mo}#hwKEK zO5hYH(fF13L*q(Ztik3VsU5TOWmc1I2YjwAy%`jU_u7B)zWs$=P64sq4H>ErplO$% zw95SIh_Q;+4NFc0+n+Bqd8oeE;w-CXM&?pz!*W*hiIea09;7wyw7xtnKg~EWyl-rf zCkR(AiRmNh_tw1iHM%>K!7Rhyn$nI$63B^7O3FN%KciiZ!V>82FE@C+ox2du>Zmqs zP{HV8u~{a>hCXPqQf!KoJ1#W?%>o-6=N#_98d+gKw?GPB12R&%P>EvdT+J>b9T&FE zX9vots54k6`sl893s#^5Ud>NFNpVbv5Rsn5)HsAPJUaYmGuRq7qZ@S_ysG_QKm*kg z@}R|%90;T#YbmKr_LxwCBAhROxCN_ZNol@~^1Ec5fZ1zVn1>eI)z);kTSSkP@I|PX zZrFn6Gk^fD46KJ&AFVs94Gwq3hKmQw-#CdDtG2@YKaSY>-sWF{amv6XW23_)_v>(R z`M!Ah4zPYN!pM~Ud0axEhWB8DxV+fm2|3CQ&scRhR0o>9`%G!X1mz}G%{~0g^`jK} z>F{OT`KzY!YTGEcXk@71J^*8xEYA!&oFNL-SbNA9}VPoH$=)!d!8=d{v>!5k$qZa&}I|Ww>ABG3Z4_$oT=)Yh-|+LT(xXFUFl1)R0kBuhd>xAHSU4>oJzXfyxhCx^a2n z7>Zm6cBb=On)1D#Y}MM08C9^=6Y&-cL%Q_~eE8tRVRH`P5@J|;Mm3!eNs9to-A3bG5XD>4zO^obckI|qIR6f zcJJ~;e(ZFtQe|1i0k0$OE9m#$A>!1H8bJ$Zmp~rSyRER79m2cx(XAjp-rjh=x-V?G zx@zZ4|KcD&eHtzO0BJ+F-Y^BeHN)?=SFu0SrAueR!K)EjQ{1>rt3CNRnFry-(c+L% zXm=i#uRbK4oz*(J{QRZxEgCo`2*ABRzzc*>4-i5bp2u6RF(=gGoLWCU@!Ca$&68Vd z*r?X_oXeHi>eQ=NNEsPPnd@`yID()OXU!xUnh?KSF+_r0zVc zcYUAfdM}eE@_9{%`KYcd&*jFlKA3J@WB^@ax0>TwqAg(Hz^tUMfu`5xw_jjONh9LI z{=!`ihk+gn8&TlAM*5;3$`$@bUeWHU@i@PU2@% z@n~wy3%_J{i-kaH&3Z)J;Pz2x2GX885|Me8c0Vc1fQ|W3P*07Z-R)UfLt3n&U9^qK zZ_M-!W6+b?o1|cI;fQgCvVh?#|FlFXtbr!iu<)c0fESnt+^Kwfq%`qNGW{`a7MttIAHvUOp`HQU@Yxew|ToMpSyY#&<#Vh z)&9-%>u^e=o?B&h94dWgNkry-V#@Ek7nZm8Hwe+6ruQwAlWn%r4r2{RhBK=*70s^H z#~8I!g+HxN`N)0@bFtY0TxgIXNUSPZIZ0UDFVCzZy?&3*`ev@(cIS{hM5$03F8(e+ zC8d`JImu&jqj5*i?aW{@HU7+9X!%|vh=tQ~Zs;yYo0wL|IMEvFnUnJBwhI*5S52r(V>SzCYq>v*Y48lYf`e_`x{H_qY*oGsJpnky7^tf3r+P z>qY2SC#8)zyVH02~P{r=Gf?OKZwuLy>33>X{j zO>oObZw!@eEO!Sta|d@$P2#N0FxzC1)x^ZUn> zFGuLncDX*{@;#1h)m2zn_f$VWGdPUJ zrfv5*Q<4;AutKxsIXC2%+*iZf_3;^hB_1`PDeCUbw;+K3F=mk(R#|CQM%NX^g3tX7 z-}tpmkHT;DO&#d-cn2@K`#tt+f{0>dw%Ocfa0O#x%1KH~3t*p-7icMj>=WOHy@8;d z<#mnb4Y-c#L~jvVYRLmNtv;YGcOA76$LDd})NC_@`Q9EA<)x9W%ECKp4~mAZ!&_E| zE(!f(0p`cawY@Xc_k{(_vUmOX8NhkOZyGn( zv&3iLYemOP;TBfu%0JXX_@;0(k;cpVjg|OG5^*+Lc)uJWO?W%ucL$)%`(vAdaKjb? zcy#PW|Jw%{kh}Z(y;{QL>0do_)eE(AXa^BI(${wR^dLtSP!o&W2H(+WEB3l4t@Bk} zf4&NiH#;RmJYTI1T_37HYInajSuNmm0-X~-uRk!=#Ly4f`F9s?sZ_YXo*xq0v?g&z zflbGuiWQ8`rdE#pYWa%>C|L#qwUGv?VAg3TT4tyf&aKYlNf85gLljH~U8p+gOn(7; z)$d_3!mz$wN_5MTjt~MgBz{Pl1bw}E@F4*6Yv0cUVBL|z0459rWNzGuoVGHp1P!dt zj^iY0nQ}Y*5*(uO+9COkwb)GBjSkSR#q;j zYTT|D^SEFyu63Bv-#kYp-cIcWD&4vdOraDmc$PI94OeaukPSXRl+M;MG}@TiDXOe2 zbf&*h|G@yKfTAf&K<5%K)6{|tyW{J72iy`I{vB&T+_Q_~-IJD%>E<~n>_rsqH-i|> z%Js=dF?u2WYXtl}>XyHZae%|TBME(SA-QDo&F zhaTZaN>2%tdr?MUcNAmhFJdb&v#N~!7W(~rrS&B2)^S~tEJ#2$#;jvzcao=DSHUq4|sq+-cdP&D)q=34%H=xG4nyfIrnYkj3+ifXT16u}pYQZCS< zlpf*{B4kyB$YA4$?B7lRb$3xdytnq#4p3@<{yQ5H><;22Z}cAUr`#|&CyFI5`eQ94)ym;1(xv5w<4^YGY&V6g_w+vDArp6MxkG_TUZUfn#=D-a^)=O)vX%a`(jQr6`1*s_O&4dbvpxaB4_y^&HWSj(5 z6Upw2|Je#fe!i3mGb#!OcCx=Pr}(mIYlMowsG*v_Mt?R12buc*)kQ#3)6xs#?0!M& z(t0xM(Lpp5^>dh+IbQrFdv%uUiYtKS`iO5WkUi0ccdO&=VjJH5c0u~~(AL0Q=C5vI z$^n;Eu#eoDyRo*HDxeqB{eFUqzOSx7P!6z?J&tqpid4rkqj~A|nhEpdv!Y94hGw-d z{ewG21JNF&#-h%9C{GNglh1H*u_`@+{67Pf*0|C!Mn{K*U*7_R9LMR1fCjH5HSQe! zb%bec-`CkByC7n<(5U9DDF~G;Q9slzB_)$w6R_-%M|BH0ci&biyZiDmDDB2Wx(<%_ zT&q(E1e|$-AzA(ba!a93o;hP#De;`^ACL^<1XUd!_-}7RRED!py-!w$MwQy#2vERC zw%0fzI)#;5M_!ZUV4$(_8Tizp?#hlB_7I)&-~L2SXCj4|L^k^pp5|i z^c2m_^}f%%c-2=@)=>x=jadT+U9G9sEqri8u*YK6D=DVRG3Wx2ADTI*D5#^SNht?sxxR%yaB|59LK*zoY-_>#Zay|Q9d1p=6 zGe-4WFFO3i7Q^64_fyXwTh8`PB1l27b|O%J8*Eza8z@1_R9Fp@g(KS3ZTJ+8&Kh4o z_s2PGBitcZLV(ZwA8piQp6G$EAYoQH%W!l@K&0YuW}(Y$2?15I}abEVEyLZRT*4IYPi&^&WHl?>X zxGtDtva~+6o+>7+Eh_H!u+K9L90WkB7le#%J$DnHhqvWHn&Z0xb~ohk5JIT-TqL_n zb5@lB(=E3WGWbqz^TL5ivXo_>DGX zpCjtrhB=$cWw5|@wuNU@9D-?3+eA>qe?BaJ&#zLLvVWWb8d%NGw*m=sWQa z1z&F9_l*4S4F^~%*C8A54-aziEyh!b{WE+O7==Gl4Yg9N4KG%#P+?tDvLi&w_NCDs zBi#$adPFVG7egtLy(+bykL1qb05@n$%N?V9y z>U#V@btoimlhb}B)c^g+^^8WU2g9$(G>G3Uh|uS3BS2{2bZ5{@Qjsr-*N0ry$IaQkL3!^qQJv$Q>fTm|)ZF?3xICvl}zh|ef zF3}*P8J>z*e2YAcoSz9Ps=?}vJ@+nWY-6+RGk`zdg2+v|h{oVTa^m4ps2x!`=q@*wTtZgtF_LmT-t|=+cIUXhoF!vg3sU8l!m-Zcf z=1nt>QwE0}(QTDS(e;YeG?!Xc!ox#@Oe@?gGZ+fu~5NFGInjCS}i3(ukB zn2h*ui{|Gh=*TFzDm|CU#Njf->&2Y*huv#){$@W8uR{;5c0WA+x4ZU$34o}_1~M9v z50c>99xPB^{^yx)NLA&-S`r?W|Hk1CXO;oyl+)_980j zg%1N06B692o1!V^n-s3Y+rgU|mk~PGEz5Xo_VTIHVQ<4QFfOZ`-)m8PnHi#!<3hnDb9RCJ*#d z^lCXBsn2d23^5ul>{a8UA&)qrzQSH296_9O;1sm|HE64lTS{q!@q{V}!ufQ)csF9H zqn<9&t*EuxYXMpN#|ZdrKZM^uFe5YSLiNs-pP|2X{s9yBunZFaDf+BoSiM|aI3BKQ zQ~&+XEt(rwHeQ1{eW~tTP*poz^wnK-o*^1oh?o{vL1AGZxX;$k2^K$$M`W-Uew=gM z3rrFn6(mF!5jyf4m$vBr7nryhlMLkb#z z{l+VRYXXhq@Z*l3&uE=qu`&aWt>?@#E2rE`eC^HsTdS6JzM5v74ba9QPXZi~Y1*2@ z9|7IZZZvi;L#(m&4xsVBM5PyZIQ{+LUmpnI9kPC!Zr`9)i~B`4mpQ6r3zS`lT5@^p zgO9;0`b8sJERg2!l6+E&qHF*J3E_YDMBz`%ZyjgDb#8z3gL03?E(0g*6Ze z%`3vYlYd%ChP1bk%&g1fT1PLV1)!bGLuhHWYYm_$;T02(l5!Hma|ysey$I)h|CI#= z0hA1vD|*i+K+R4u@i#yuHkw+@WB+mk_Dmy|2j;8LALd-6G%gs24y}4ONDilaO(->i z(=GK=IWanR3W(A?wzgF_NHEDbj36AQw`U^xy`P+=MU{;x;KG!oD*!jtuIpa2<6%)9 zu)p%N)pqT}pn8YQz*!NTf&qWK!2LLcj{prDdPeq<%e~xwzxrmMtX}nZha5PK|BURe zNzn+YaLmp33vH$2Dbj)s5<~VSq|CDrrSvm+w*|4PNZ z32ja08d8h~h<42v83@WAY5J)=|`TrIj*1LDT+`b2GQY=0o0<6E`az1_0X9J_Yb=g;5z>w? zPx^%!r|n9urPz!eJQzzKhk`ylwz(KK19*h2cpSDv1fPBo0DNsT3>3tbw^*1Cnqv)0AH|V5m$1O>vgd99YWb~IdlUwcsm9h0Es})eN*I!0D zx)Q8{rczSdc~`F5n1*w4KPa(BduGCQqF4v@)fup9>F9>qi6;Ags&7X6Z#?2Q+tO8H z)^ebm`SO4GAWi}ralFq5wr0CE0*7z$r8~ZZdnH7CVFjIoPSVr&{^c0_&>Te6%Wg}y zZ{@yA1XvoApS6C<*-JOV*DgllKyg$JoRvc4FNF6fz3TzZM8Bv?)=#hUU&u<9%(dop z)0LhRuLR3rHiif0dEu&h!PlPasRkV}Qu~^(-$Z%KU2EIjEQ1L*)`YF>?PvT_(xBp2 z=vTY(v}M%F0DG$83A$#jxPw@v4gep<)&1 zLV~%!!IEUUZ@)ljL5G?VN^Oe8yo~NO?jueimTb+ZnjlF>01u?bcmF0zX7A^ zd4TB=e|cElGhc(bok=I(9K}Sw;Lc=18pVP(a4w(_b&uDq9o_wLRM1l88Wdz&$};}w zw|g~rRg`QeG{iyac~$`*l!TO8fHb_#1vrzY;noX&zbb@@TZ0(K5xTEog`+Gcr^?#v zDlg25q5y8xFAzer)61pX^!SVS2->jKK?LhqFy^5~=ZF z>}{H}v>2I}bCy1V^}^X+K*8$^@1tF{+eTm#OA3BOwILUW0DH^~~Yr>6FQFnA>B!3K&Sykygd6Be&*$*87gs9m~1(j$4|?H%L3+FkGvr zR{IA+M^W5S@i%vWt>f)inO7@*JNH_2b%%*!g&TMvsfF-hje~Zp ziN5bTI3?G4_90!&bKi-UV1|4y9JLUoUV*%Pd;*n~m!Psam(BpKX66I43{pUd~nv08&{a8C*Zg zRV)|r@{!gjFsxJd=j@uAzhMEqMSGto&<<~^#B@Fj;q9vI?i|CO-GI+iktSkW3*J89 z&6|!!#ftea>{I`RJ^mP4v-OYU1yr)vyokH`<8W1O-kVUoz=wBPszDd^hs&l0VR%0d zMvmSY%J|4^1It9Q1Q4fg@FN)ayzsR*0dI4V?LpV3bN6CXGnTW=l{#anGjg|G2VA-2 z6lIAlmKOcBZvBiMI_G5cS+?=WU_`D+5@uHV^t253pU;;WnpNUOB$8xRi~RE5^_dyG z?qWrWKAYS}xx8n1DuWfrCnp3wJpsW|7%>bgh~Br&+n$+TukF*ze%LD+qD7~TdD3!X zBzC`#Pj|gt7(VX%K8?l#v6#5f`9^3XlRrL4@Of6tmglCrLuZqGQsBm>ruyzIG19;J z7LrEI&M7PCX$5qw%ZP5z`YJiMf`o@o7f{bV=(;YuZh~5WWk^U#sSSaRkS+MWQ5Aj9?Kw@nEGUi!{dIY?ufKLJgnJDJwqsltBqs3y z`TkW=BaYI`h-82XKDnnB*$5Q`_nW@S5;ZFW7KP`J2*@h46FbFd%KfM>$}jW_HQaUD zd>C6h4x7Zb=_dF^2qv*zsWEHID9iDKjz3F7)QTjO%Cj986Yv^g4QJ>IX|;}D07~8 z(o>IxnXU_e;zp7jgHM+s&R!xpN8M0aW1VcNmFL$&!S^%C^z{iv;8+j)7O$9Q>C9+TJt~S%{Q&okFac4AVRR z$R_%}S*X?8M{hwwBy+~Fgd9MoBeNJ8qZO6(Q?)R*-B&^!ANmpMsfuMFcfhhf`;O2- z2|hD-`Wb`90A&ajN%lF6WoqG}L9l~G;;Bi|YWG~~IFoUSdBm@|&O0*tOtY|^FBv-5 zMc`?ISTXYmHg}n8x&uDp6!9f#;!gs3IAL|UOPAATX2g;S6Y!s45a3A6Dhsrh(|QEc z^DAlyCJ4m;B=2!ULsi6i^9BUlM^Md@D(s+rWZR&_B+2q5xzr3rLe~#pL{h66lV?lR zBEAZdp{0zn2Gf@hB!oKalCUKk^5m!`v(v ziO^fWlgGDQWf+J{p0@Cq##eq`F-_O%LT06;@150DH+UKNBb06m=^qO(^aBJ16VP#3~T*F1|Im6Q*l%YSnWg zY@grkhX)zfhxG38O;W13Tt%cDHgsEy%NF8LUNdmFL&`DUg!)lxTMRa;S)#W_*ls)V z5f%N6rFBF+H2$N;E{7hkW$vMZVXmq>GJ4VvAoA9mO`A}U{R&%qA zwJCDy0x5}o&wg?pakFuV{^`7xnhzVHJsFf~W9Y#mGG zYyd6&i-b2%n}mD>Hj5{mpb-qujy*aC?sGgnUNrfN2z=;W;PzJDcq8Aw*$<1*X`BBa zgOV7Bt?>A<-G-l^OE9rYP$wL?H7o(fns0UP6^H*-Q zVvSAZ61+BEq>z{!M|3njPlhBlDFnN4ScOH@myd8F zZqOG`O#3b|E78?U`S8n4g+G|tvY1-M_sky?h^t7Dg~K4_0m-#C9|&53@<<*X2Ed|G zF)@W?NVkW#5<-lBBxdgUK$V8DM^JJM>`vPaX^)E}e5BW-dkE!*0DPPT-#C0*A#-!a z^x@-^^P!E$4(N9uJ`9LC#T4EVMItdI6q9I<8RBqf!d2*4v2+WFL?Wh~Pw`aQ5R~!I zcs0OKT5L7h+36dtG?v8?_ZVpD5Hox~IU9XQdR+-rn-+xGbn@ZZc+eGOLpn)TM;vRQ zaQJOpOt!|k^-6vYj$FJoRS>9ReoyvSlb@lgQtT|>Vr9>{ygG1XOe%F-;1*n|gcjv# zGm47IQPm#5RLvn0MM3#RgF%GEDfR{jXfUG*_%#g2{o!dCbtL(5ASU1U#$)+NRxc6~ zGYA{|eI_5S2M9oN`hUv_yAT`_qGnieYb!_|Mr;l*!ZrHN1}d>8PF_lc47k&1R>H}c z(O9cPkI7B-XRtEDth96%;mKES=EIkn_lfB2hZA`VXAFtM!Q|f_c01qg%_E{Dp=3z7 zMbF$O$bZF)bl1enfRXxIX#IcFDm!qqKN?YFN?WdX{b>Fuf%jB z{(POT;M$yqq~vou=Z&EP+|lZRZmQ9EuFK@{4fg3PabrfQU?CV}jcJZVQn3D5eW1r| z<#aR=c0|F<9yUD`Nx1)e$0oT9oqnaRDtwqBHl?8<$v_Ny92ELodIU+{2(fpSJGw@y z%pz5QJGEwI1F!DNzAHU64wy+TK01t$LzIr68}qD^P?1M?JjdQS15^)JX^s7tyth80 z>FIgGM*flHN|~_Cq$I+*HQpq@dwuct<|0MhbDrQb*@Q1aa`-suegevZ#V6x`-~Wmx zKWLawbgF4H6@2;M7g&1OK40;cpDNb!B60q^RrZfGmasoaCRwgtM>5@$eH*gHZz(^Rel>90uEjAnrUNe&mtI`XFtEc4CHQ|&)K>M@ znMA+e`C@lA2MuYAduv0=)2Bn**f3rVu7bP61AX7pB=R>(%ipEFK|)+T>S=!%jc`9y3d}vg!A7S6i)-L-NJrynpb{IabmbIfpw_o zVnU0RJB|vh(r(n;KFriC^G9JdH7swMJWVWa3{94 zNpiPwV3N{pf@mQ;!at;uRB zemk)vUBK1UfEj}?5BYx&JtRt44J+3=ViolLh0*d(yr$wls3pH_E z2O*MO+m-V0)Ynjyny%k)E&dNJ7W1;$UTxo<>E1tT>-sn2x4bIWRAd`q6)qw%ZugSsU9}k-s$_8I^LBmRuXwCuli2r zx*{medrn!@PLuuztf2k__p>X82W<$iyR5aF5??5yo?y1`e6nToaXW&0t%JKsXdDCY zGbIw;Jgxrl`D{nkkaE+o;Uy{c`#)K+Tso_EQ zRr7{K6qy24ENIXYSC4IrYz;=a>3sYF1b#>fLN7fxZ$TM(qpfcp)}-`kPPz?z?7z1b z|G%eSRwH?CFvV&2+5?3SRrVOWz;%5c_tcOw#pZPhhH}I}GmG-*TB6nRfXeYYDGNb) zUjqL9Tz_ik6(RT z0{Ce-_>5mvegAowk@^0B7(`~w^v#+Us~4--7~=2=E;GIwJ&5>pL=c}_Qyt;k0pM*mo8t!U$r>9WNbc=;G4UsP=`QQ#8;+R_51829 zBhoIK{tK9%pDnLXmog{IKHh`z(q{kDeA;J7_xgKG5^kwD>Sy~+cKlv6=O-FqtijwV z9vehZFNxRgYFEgxRmFME4K5lW_CY2{<#Xn6J&`aiV1D5mxJ6f>{{W$% z(4QFg{gc@_CGlTme%(aUW_n@uZ?vtV+ky_Hg|TlUe~Y+Lgak2mWAsj=Nr6;@LibL* zTW+>#LTXA(^+cv}m zpc~2FmY?{-dQbjw7f5&Hbsoh{U{UrlUo7Mda#BTFX9Z8Jl0?bg)5rqtk~_vxJL=E% z?hssNbS#&Is|X)i=B2iPHIHNW3q?qRm%y~cBI=~??0}#j$SF`J#SAdZiG(u-=-o-Q z9Z1x*%ZSZnCByZCLh~pZQ-)(BE^pdQg z$`7ZWdus>(3|XfRP1-HMhEWXwAZxv~FiwuM!Mk4vWz=*bL#$o(Uh(+0efpo*^dCoS z?t7Eox#HH^X@!Nb~lG9!eICZ?+4K_g~m063D02-v3NH~*l7spraZ7_mHYga_!otS z$CsiHJVo(QlGyy&jD{qjGhj&LUFtijB)}mSB_*UMdVb$BihAytRBqh|8LEEAJ#svD zAiMB>V*lB+*{0ABsZH0V|+ap|X%ta5(({^}?yu>2G zF^=S-Jm|A6T`1(ZU>C{rk7tZ1oni|4-Ox?aj3*BLqh7sSO1?;FmH=_Wb_uP*oH3}M(FPa7MEioXz0h``EpGOvfa1S6frKNWL>b0>AS^>eT1`qyp$wU37)5iT8=OAEHLZ-d z-&YRjn@JT~TZ18yL_2XLk8ogtEyhv~+*2yw+s!!YJ$f{}ET}5E6;*VJpw!iUJ^Z?U zpNDm|E}f;QloD>KOq+7EZVdAC(so5Lm~-)RFs<8@%I|(?sMh(B#O3i$`ywq_GsO8w zw3j?5D1=w zmJo#Ce*lrr_}w179~q-h4})Vva_?^5#^(qu-f*T-wdfRe$FY1aeCrzB!i&V@c>M1` z{6o_Z ztkfV-*OZ%P<`WyZcl3^ zT$SHujQ1ys?|eb(M_oI-R2LHUBvGT!3lDm;$#$Q_*YSN`F@!79LpiXtx)3olqg7H) zQrwyjOKtx84|84bj%m*?yLmy3aD~j~W$|$hZZ6?J+`G9VWA_9q;Sq$rvlhEnYP? zSnF4!nA;L3W>-;3{;<>USS+Nq`Xh2)prcH=M|Zc!WG2*8{c z*+*I?FW8X7maF|6e#`6Am;}+3kBI=A9}+v307k16g~RNq3WG$@IHYkb*TB&P8|S9S zsWL(7S_@V#3l3F@@-p73{@DKfy7TEgc&lgCw&G9nJxC0c#roVIY5oZ9uWyi1PE@o9 zbw!Sa=S;Myq&PN6miR|mD`l|Sq!9!RNq;yvkI!rer!G4&c&!$Dc2gv1eC3zP6d+K6 zCGL>|FhC>_5>bHSOo%F0Ice@%;Ia+sXrdjZu5UIHUwAxQx4(1|v1>C(d_C_fRfR_yk$!_)_z=;Kw{CC_>K7+|Wzlixa_-VMuYsMSeN2_3T9e*S}66a15x6VcYeWUFFnc7O&mvXNB^u{B7}QQYN@fTvItXR60`hTu5ptezxYP9pES5YAk%ff&{qEqO zQo6ZuMkHhrbH&5oMDm{Gh1b3`FR@2coh&5yice49k#4SklsV|}GGi+21mE;orfcwN zFVh1ln$~!R4x>y3QxBJij zck3=rmZby=@_@4ZzO?*F;Q>WbpbkfEKr%oMtHQJcQg#c&ZItV=`muq;A6a?lBO*;2 zP1HB?912~4B0sMHZ}|Y@WlJ1z=Z_$oCimM-oJd^|OdxKsCcc z^_4>ce*q4paZjPtVlDXWj(j{Pg@GPwqz|f!zZtH^-XGF+=n=Zqjk7%dQVCz?F)_u6 zAju&rx${^0w`U!lhPSyWVHriKbIEp3`4L4Bui%^FHOqt97c2g{-FL&OE_I z3!4diQ2agii!3gpPs)+jrIvJ@Ku`H8qA@g zPQ7a{HL$#1{?5!bA=2a`?!3O#HXO>%FI)*OXr^=%YykiHLVmKyPxO!4}|PGr?zULR`F?vruR<|7<=Fl+nv z4`bFiUEw?cfg@F=`9o+-&51eN(Je=C!uspQ^p!OqHZl1cK9D@@`twr$Iw9ukYKLyn zol*70{d@5o;ekh6G2i>TLgACyeITViR0#T86}%7fb!5X&6XC7Sb|{cN!dU3 z84&4T2a=ZPXoQ3bSjp+msS91oeqrJKl1$gijPy))O3Wz4q)b>i@k?1E4?>KJP?Q!& zt7pA&th6Nht8G2AsL42>f#}pQDnhifo0}O>T&#k^Zh?HH7K4+VO3cgfxNn*g{1K9m zB_yXbDkc!z^C3pc5yolTp}bZ`ir|6r-JhX#{SY*3n!R0H6cPyQVI*nn$q}s zoUYbpQ#PGvM}}mV#>>J-d|IQRxf*S`!=Ihd_r8>C#tFH;fzBE9FLt4Ms4cP^dIZz_ zA0~L`%pL&ClYd2hAfNApY2F8bo;Q&XEYPy4voSwZrsT29DKgnMw5pL*n3tG+OGH+p zL8K&=u;f5JzxHr3vNY*r=_)NEVn^7J5{IL6R!GPxY$oDHgvl3<^<7rki0ha29UhVC z<7T~OHaBW^pk83+B)9Q`4C!B+jce>MG}51b^Tv%r8>y12rp9eMOG)nMxo)qw}}VSr}*_7XG@%u zmUbe1WV{zd(rV?<4~T9%EBF3`Xf>ax-`)u%L@elMVj|7=Hqv~M<_0d+fcjkJ2aeqd zSCl#D2hLRGD}h%(9@rA1D)PI~vRO=g9v^T4wf@U=$eltqsLo)yIyf11Zv=fF!URaT zX(k$D7eVH}QlTn-L*evJVa!1nRNF&q{N<=7B!PzjD;XK=%2w9k4$X_`ZeXw+{&Vg| z7#un0yYtc)y|o2WaJhJ78c8l|v95?S6EfZ8ubfQ#LnXns%YJ2W@4@^sv{FMsBfqJ~ zqb=*6!s?jJLU;PQP4cx#g@qy$LVZe{y#`J?Jj`yA(wfY)%z~5ok0#+u79k!HDC!(_x(B3mHdR zXaxztc!Tgs(g7ute_6K39%z}Vk#r7Q$zNH4kKx-g`W&o!hFtk}GK#;qENFrtt`yDmBt9UY536gw#kAT6mBK6?n(=FRLP8K#^oQ8jq#WcVVaDGMDu%K#%ImwX z$8|42%!&Wl$kqJx=6m}qFVaX}4~?w)AT2+lM%ghTF(#|>IJ0zD#?-sPGoS{NgeHTP&^G>kK&NJ~{cbl$*^zTtV=iGNZ zg!->=BvE=QN+1M6?&PXjuc@_Iy)@1M)`k7|6@v?fqVc#xAuaq}LF65uD16epOXE3=sYrP47KJ#Y zQP2_!T^IzTJj&wOyDo$tWuX{=NaEGJ=tfOi=I($!H&$QkVf8i2NlE-q6luU)dH$+z zqjbbiw>vmR)&@SPTaiX;eP}#dJ7jDs^z_oQB6n=@%=Q_wmmGzJ$lXe|Yn4qjdM7q3 z@jOg(kCmpxe6FpKI<9Q69D94@T#yXJ$QTaW#wJcG|f1jFcrzHAr`zFQ}tM`*CP ze~|voGlP^`DY+pbH3_DjI}ebe2uxS0Aj-&2_FS|zdB{K~SM6p~3t`ZBYMMS>@%m9r zo=cgO9B4KFoZVD;@ZOk&s;jtQrwE-SdH+8&eT73+U$C`w$0ejeE_Lbd61b$afP|oQ zN_Q!6flD_(y1Pp{B&53=X^@gG!SC?C_x^-^&fYU?)><>uGmnw4_wgTV1!~x%%MgG_ zU0%{9Y7}1HJ#2l`HT3>H$B(A`pfPSxxj`B<% z_GXL+gOVI=mK~;;1n-CJ)`(AA)gp^DHJ(aUEKNaR3N+y^ny^^?f31tCDh(_-SA2x{H2@5WLm$%+IZS zE$;V4Y1X3mR9^O~j%<@Qx8gI4eaGF3kVALn@J_qCYs9vA$El#_@2Cw3VRs0EcKls* zO&3PQ$8JE)i!}ZJpAh~}(m30tJ;>3@zU%isU`((i-e;uEXpHMJ#(IObzg)#TQ%fVT z;oR|=hwyE{mw3f8%BgkUZ_7pYh4|f97i89-JVGn4DcY2TuM=-82Rc`JUJ5_m<3~!PO=J+<8#isl%qx zm5Au^2TFnpZLl(lgTFE_Cd15$g{Z$(kZM|o>EdXFg_X=-Qypwr8Mf0&c9+8Iz#RVn z22X_6+cz{MUGa9zl7Hp>r1`pzQuFgqm(OWj=>98<q;JP`I6U{}ZAa&RCLp6FxYx zGWSJ^{r-COD~OaB`fTK06ZfMPxA=>Dn+{SH#v^f-y`%T`B(7taTNxF$H_L zk>GQ`VnrcT3icXBjuj*SgRzVY%qQjT0ZCgR_JJ2k_$}g!JWZK85!H7r*TzH7V=Oz_ zByI_7=!BVx%aeWaNA}ku%ffm4o-}fN*X1$?G(VyqP#j2)osSKtWbJP}P>5uV;T61% zE2sGI7f*-7JDW!^j>`XB-0n~${DZ&~l3L{>RjW6ZY{5b0dkvJVQVKor?-(;I!m%y2wjSL77H{ArG+(|$TR6uS?3c= z1-J^8HM%z!8h|(xFnQ%8XpxsSyJ3d%A~oNuR7#0FZmy(9D+V>o+EK!3DeVut%iGeD z8u(dCYV34qSukhjB=~xQSbm;}OqV8(6?G=V(I*?~l(k=3Bdh$-Z$pFq`As;Lr^SG{ zLl#Daz!V(KGZDKd{UHC0S~zIUX+b1C$h8bI?dPc@6e^nXX2O0%{nK~U)sJM`$prSA zN11>iY8eR;E@a-KRDAsV9IG&_iy^_Dxa=|E@@b%7JSOaRkBuT~ePMcO;TPT69ZvWK zOHe=8Aqp?w$jREZZpUVfZre$h75)H@DchWsG0iuTWVkWuUSdC1h@#lR#`#F_m}6_u zhGgV)APZZXdu_Z90c&K|y!@)hH*}hbqqZ6s=dr$6q6@_Sq#eGmNZ?TLTO9DTw5f-Z z^BlMEa&+mp?vNn%Ma`8Ep4zABU~?tnCi-eiE&8dutPdUn#*3V$E%+Drtq$Dfz#+yzn4~|QM^L@(#78{im zpuXNy*3!gM)D_8jyQtk`6;H=9@Bt6NZtwqxY>`edVv21()p#%R2?#&Up(sJMBgJyR0TNn)C0@n+339j)fzrP0|cn;ep2|P z#bu?zu=a^fPx~ktFbmqz4CzbW!Rz1l82jr*1iVuhK+Sg0LE*%vsW( zb>IHYSCVUX_RT+oIggoZ(fCk&^*zRQz2eh%mtv@t^tkMD%!MPyUDBLE(aNj8Px0q9 zk{#X)nf9AEAB?Uf@}tFcn2QSH6B{jRKZbk$;+6H9Fp}?biRT$uZoqgK3~5#H71U3{ zbm{GsYNM(TuEf7FGA>|glByIM04f5dZUFN_2fyYN$7>053>~WaZIzyr&FJJpJP=oV z*c=IU(Be<4RYLVG7gYY^cmq>b>t+*It!IzDkTVU`48~Vf%LSuNTU`tB6#kNO!82N0 z%OQHFE8IlH%jyi1*&`E&cEC@?n!X!>Wawk9#PFl8r?Sy7(!RH)t1rw(@RnUTt!L!L z-3JGb7^5L$X-83z-sHbwb=z5;)e`*DFi=7oC_xUJ{I4jhtH5?U%Sp7n!W%!iu3eP`}dkd6(ua9NT0lJk(9{nVwj%)WgOC|!+fHw#0X`-?5PCZ_i$E{fw|nRrh}m_e^ztgbP+RMh>SnP%&@H_P2*PNPcNk(>8r0SM%^b|a66cs4q<4?FRR0>PO=!y z!VktXzL>t=QkE7-vB|A@x1iU3C7j+`C*L-+wq8;jve^)FmY~?RJ8wuSJ zZth8%Px+ta;xqC2@{!I902nJBVm zrsgFmtxvW0kkWX$(X7F(GUo+T==gkFaw09*OCOO-u|fi9NTYD#`FaLU5(VijeJZk* zWZ7RyC*CT|4nVI+J3f(PT}{k=>P|+QNTZSsdz;0-ukZV}RWg@L8APAnph^@YAI*GDY9XLLG#Xe`I&{T*n*EJ0+(S^^C|FiQp&e2^3dn;-c(|sYgum z=nTwnzVYEifrY(k`Ic3?V%9#52@j>Av`q{s@(qrHXs|wZoVl%g(EH6?`BDYt|h*LCcNr8ecx4f9FZb$cn>DJ69@B-+h}Lo$MF+^>9mlWRJ9qGfm&xPT1q z83d4%gAEw@sR-3Xd(DW5V=J|;^V)-BY>i*a{cOmSg2<%?-~49!ljfgs1FFKuT#~=l z7v_k*Y7vd~{d^}GID8Qd+;0?YT#5yj93@B5vV|Onn)e{}b*_k?v2TWzCkBp( zcfm?p2Mw*1W2!#&T;v4}#5Ty;#-tXjFM-i@IoOb?V(<{RLmGY8oY>T8?mk3K0T|E! zQv`=;+CMK06Gca%wG;9n^OF$qP&l3=-0bUHVn3){*JpaIQK;IWuhheJ8ZN_R2e;=u!zNUe$@afW8+qK4N=&XW`#B%bR_kDjjBk&>&s;1+ZQ zp{*sfBo?u7r~}JJwk7kIG$sJ>d0*};?ymJmHoKxrL$e0=Oni-8R@uZn^`@V)4Ot}! z7U`?bTi_F>_!4}+BkTd3sK4^rN=&xPBdC7lhBTE{Qw}u*(g6!{AUa-90kO>Tb~<}{ z*ox<8k^qd6rA7@k?@)=~@KT(CwA-zi7=P?c#=^Q%#H z*}aj7H%gRNJ9`~iOoJkG8h)h_rgIlxw7;pfqMr|Z0Cqc;96Ilhwn>5HT*cbz)&oBp z|A(2MwtCcE>I@u&?tcy8m4Z>&Cr_Hba`?^k5AZAfFEF;z{sN#X=!FTu9ZC=++ zo!zsZ-TEzdmeD`7^Ta3Rf5>9XuK;BUjSGtD{dkJ;R-S@9XsFSKR( z#A6^nv^Eu@&1n}o|MP;JH20r!_+`1{X*&h+l)@A_-2g@qVvK3o02`^J-#B|_ciEyK$Vq1LxZUdT@D~3p^$Igavn;nfJ~$o_k43;j6~yj~0n?3M&Ae zO-&`Pk|Mb)P45LJjG@nC8F~FHzL4gp9mssy!;{MUVWrYtk;J{D2HRLGp$!XQKrmk9 zd9k;29;G5vD(LxEJ(G@-E$8Dlj{{eD*4OQiuFJ8g>2`5uRBGv5uZ?Asr87C%eXj` z%=6Ne-5vbI5&L=dtC_fw@1sM=&sXv7%*}s~MQc9mJ1S))DCn@&5C|;q{%DPL!74@~ zgh&h6UU&@-L*B~RUc-ej*5k@fHGZ~?&Wb6Q>H-Z1vLP^fP%tZNMzpXtYt8K>1t9Cx zEeH5p9p)0t{wXc{i1XsqB?Y8>&&`sWrJmQYdP4E2V&UMjVK#THnRMrs!|+1FVh{Ce z+$KU=69~Lu@|iyWAnpb_3RX1EA>oud!bXm5tTY15%wWD--#_ zir{1v*6Ver=RH=xBeco{ld?F=g8lV#=0 zoXtZp3Be(JoDCrQAqG%^I9j=FCS4xs&JPFiyY@6h_dAtyGk=6(EK8U~rXc!d-^fCA zA(x=2(XVa$Q=v$b_2+bBSneB3M0?$P{z623wrKYBFOl_wPTbBqFW>rgvC{Pu@aq*1yeN%9YX&=Rg^Dp7{+7pRhsefAZo744Y>irn0?g*C#L+V$$EV*}|>20p6 zzn>hxagrw9wNTM#1oIo<H}1xp24; z(||eh;uaU^xnK--f1BD*n>B9yK=RZyiD z?ML<$^CYsAmucOaWOhN8l93>=6{LU?6NQfHte)xrjqW5qK~qE9302_KTe)`kppvXSHvzwrGJ~q-2ywxFHLUHYFDVSx_)(URie&!Adq z`yH1YALXUJA0q*B6BQpD3mx+=p1_HFjgS3cg0^{O{d$g@0GhwzdSvd02`tD~{jT#j zrE&&~I^Pwtw3Q-tlmUytevReA5=%=t@dYjGLz$OGz_(1d>d%ffYNd?-k#|$d2!smQ z(>+ct>V$@Vdg7+`-VGi0_^k9ZwMs?ZhF-IRl=QgUh2kHK(MeSegG{v_HKZ0oh zEtQ&2&ZhTR{HM$+3@a=*W0XKEnX`Xg#ukUExR6gEW`H&COF7&79m-FdPGRS~Ns!zCgMN;_>pw|1W{%!_n-|bAHz3HWy#wL5ZU;qm zkz6I}W3E|gp^Q)6D|A01_r=;Z1|_KC#H!>8SZL7I!_{K%cx@e={^n3M+(&c0PM#k8 z$~v-V`W6~w)Au9~N(Ibrn-!hWGB~2#xn{V|(^%l}aiJC(-%evnp;iR7>PPnHr@sp| z*FWkH4yr!%dyZy1Yb;6+vY$wS!v97$+nAfsHMsZhjPeWjs-A%p=1!QWt zOZs#|Jbu4}$*q+lD%H{jxgeRX28YpZkcYrP^Alt=S%&+J3iD z#j8G$F=RQ`Ha-EWP%@bpbO2H+&tVGJ;xkqf62-+pbNx3JrOR{ae16q{KK1z*mV8tr z=gEdb2Jg%z?+7QRpY>8xV%Io|(yC z{cGyGWViT)p9%o=cNK1mOm~{ZdJYi#?_@mQpc_LFRTUkPrcV2b)SjGg!E z@-?3Q=F!Uo7Z`PVUpIx+L)0#N#WehonPWNjk=r0K63zu1jJ*#7gEwNXpf~mB^cJRH z>6x2Ver4=%Rp$~aG^_LNIH>uPr{7lVAO~a-(SE~pVFWt;>VqBAU|{1GJ%&N05n#1| zh;#kBBt?GPXa|j~AMbw~7<>qFl!(dwAk>nGNc^oodItl|O?B?R*=ct{L)#zKvFN-871LBYG~_f0NnYSr4Bl6DD9tU} z7rI)nxr>SIBCIY3f4utHo0`r>oi4@YBPe0}^PlYh@(Z`o?Q+CgMPcHI963J#D=Q#> zlbwBhbIe`Bn;I&sy@cp{CR0uvIuorcA`y2}>7j$2naCv~NEry~=7i}GkqPVUiNXR@ zT;&^Wi?Osxi$;b{{ZAjzrT)DYTwi{K@u*syZ3-qfsIV$bs%t3{s6EbT@+5%~i4fw= zvk$4YsE*rF&U!>S|AqkAEPV=N$tEZWNyGcsCz>v#YP)C4!N#2(KHtsxN2mE?+bFuM zaa_>r=uS1$Z@V7y3mk7JTd=sH%y19MCp`w6lHk*P55osKpv${B@o|{ltczyC;V4b(AI4=gn2bC=ZumbXCkPk$99MEWlV^_XS;ow)1SQMNLs<$vCPV_hBlj|8{ zLfsVkusmB8d;dAAy#T#Ku>964DbsAPB$%$?I89Hu$YLscO46I(f+_FgmA{)eE4-k9 zNDGr&HQ{|Sk+O#7X6xe$7aJH_Hx#OHG*nvvtld_i{G47j+|ve68sp{IJeCcYK^^fmJeuM2gx%GlB<J znhY%-JeP7E-DEGo2wq3%2^du6zL>bx#0jdIj+Y2Y%X{SGGpz(x2}aTUKK%l^9hp-b9P<_FmZq1!fsX+lI~UfRQo5b=R}htF1)Wh(M|`pR&Dh6fWuoTJK#OYY@enT z0V5~t8Mkm!3IM<_iZ;4>7Y`aJiY85$2QA?p352k58o7HZHCTyXh$*l8f_&hQ3Yp() z{(IL*2zzY3uGXdsa)aCbZcL!?FDRHixQyi?X_-&gYY-e z?7ztFa}^qW7T;WHizHpI&m5o0&L}dQFt{Z4|ExzuqJo?rF7s)0hP_q6~1c?DBWiBN(w|MM0w9`d%-iB?o10%6UabBjRqVL z%r38X&6B{Q`3lSdC)e}_>rEjVSr7@a`jU6ep>N`3Q0SILVuJ1Rhb;da>vC%-OT{Xt z0$FTqreufOu{k$vFJTK9WPNa#LnzW>`}s_Fl!#G;1PDca4!@{Jv%TZu^$)2D0I7qk z{I~CMmETXt_=TMQAK1oi@{z#x-2<+#DshR#A5>$P;4$eGzQ%>kFPpJI;bp9OZnqNu z(*jEOjXs|kI+`lIPiH_rmCtvy^U`HG^`%T8Y$xySnkO1iiA3z5)YYRh3zXc zV5$4rnZ|M*5`zW9=?ON>c$CBXm_n<*h8B4b)2 zU3qW6^s5$GxcV&H08bt%79@$2Ra`AqP2rPVMt?13*+u|a!nmyBGf{Iu>W`S;;=fN- z7FP`(F5!Y#ZE_4trTTk~NE1;;9xUHg5?01j>!jhyCe0XB^^hil0omC@-GnbSq5f@5 zGL>LKbU+^>1$z60=W>eSqA){NHbP?_NJgNcn=N;(*=t6kaRDNkDG|;hRrSPDrSny_ zm>Zs!B>&TblBiHJ;f8mqkvc@na=K<16t`kFDFU*pB1y!b zMD~|!@*AqY&bCIF(U%>cZa@S47XTJ0v0=FNq4I#{SZChjiVxEG`GH~BS6hEHPfKnk zD!Ei?t8W@*(dm~LZL_|yn|Dvq|1~f4y%g1@=qlE#|GveOD#@j&>upi-SLc+OAOP;< zsPJ4zDpnsfe2vYJH*{c?Y+i<*kL{#)_e^aILe;fk9cKGntkdfg9W80jf}SurO<6Ie zs2R08vTxw;SjC^hS1UAUAeGNgP*+J&p?fQ+zgUe@=}ZJs3=@X-ZiGgnpdvIRD|kY% zz|PvHT-MziRHPy{pw}#j4Pme5@&GrUeySvTu6d)Fu~{ROz2A34`x1*@@K-6Omv&;L ze{M|;8tE0@P0rq(&S;h|2M{ggsRA8W5qrCLO!2R$Za0hQEDt@G4B3R;qs?=cbt+KQ z`JO}wa6ptlIEY80&|}ioy+6KN;6ASK8glg6cuNw^f70{UnuLy*eWK&CMm=a->Q6I* z>{9pzV}9Wi1Xs}R{k%rYP4alYkjwm>g4&pyTRZ->HVZX}Io#hvrz@vmJC$z672P(N z3Kf7ykwDFqQ5IYMmhg%gLzED7_myw+H!ua@v-A`;h%D{*-C;>weX7;CWdU^ijZzv( z!0?ADk#wof3cIy_oIJPK>t03a+1O4ETtz;q?YJWs`l@j>u^e=JFO#vHl#PIiA;3M!&Os@A*a1}eJ#xu&B4F0CMx5_?{57McD zu6)oP&p-X4qxxODOHO1)X{UKtxs_JrdZdmbGo5lGN@6uyh*VY}gIb25$3ps?as+}P zyw5)%$Xs2lB7~)wwUe{mPr*uy?+{t#q`TeFN5U!DCJo&YscAapH|If7UoxSw;s#|CP23u>#RxCR8WAU;%imz zD77VU9%d`u}`U<0?DM|0)01WzfsH+n-WYR!^y1FSF@P4OUq7L zdh#w}=H^7k4}C7HnFb1P6JC8t=F}-enWtVcn@iN(f!JN~2(k2WMUK3DSG2+MymM(j z+xw4D1rG<-MrvPBg3^9Yp5xxoAK4UYrGoLw^k{XyaqZ8(F^$F17bka$rSoLuBd%#B(X4HB zz9tMguROpSMIhY&RF}ty`gP^8KN5?hmL@E#Fb|Odx)xCz^eTzci5KGRdeCPvn&B&f z>C7ndfZP8dLPllD*0mppuMjsf%+^=+`@h65XFou$cb0m0$+Ldq*M2{y&WLZ|J#0Xib!!)GN51^cf*M06+1K zX}EY=r+HT)crC`R{a{`<-YV>hxoydxmV7`KZ+`5En00@7u-46&at(J1eeF0>8kCe0 zQ~8(;!lNGbGb-bf-+rh0o<}1^6oFZhEPwmfBw&tT5w?XEKjywqr3e|y4vaoUWl)LM zX>_9+Amgou;>reJDXICq%I|i5SZFmL+Lp??qgtywV=gbjmm+?9Xq;?bDh#AN$Cnsq z-+<*qXj3N30LFbYXhjm;v-eaUmzo@5O*l?TEVEf;K_T1b3wA!GuHY2Fz&$=iWQa$pn^P3vNoGfwa4Gvno!b%kviJ;h>3PT zF18-{IOushJF z;TX6c+H~#ZD%#9Gc$}pfx)NisPgDtpvp8?%Z0Ls549Id(c1ksE_`D)-{-oEafX+c< zqh_ZOPOp2S0*U~X8@b{;Y700TA>TPmVYU8Rz@|hEoY-PZPnd?+iFf%GH=WGKUb2M$ zST%B!qv@<{%6}d+vl7Mq7N8!Ah@7RgTYrSb``aND4roBFNc#7-O-T2M07=xPRa%%- z>#cEJ%^`fN?XBu^w`sa#`~52=%%Yq(ZDK{G&Kjn17q7oG)j~A!zYr;To#YKW`g~NY z_!+aE`7Kt;?qPx_%OpTaKrOvS3!XHB}`(OQsur~E zS@hdCj(GBZL&l9Bmy1rnKL{9roG$Y3d+!t;xRq?3gWykAp@*^dgyZ*`BJ&MlmaGY6 zGqAEuag|1&>0kcgCX>3I0L5osr|yP0zX-L7f^{7}zI$71O7wA^$-9xt3 zbYf0fwGrO(o{Wogjc@*GcLxAA}8KN{r%gvd%gFlren{X93?XBXMJpZMwOilYdF5=i6>KusGPSio%p7X zh}P_5C`g~%C-CG3>E07AGq7(9dWr~DJMHHll*-Z-p}8zJj4YZb=WC#DSR2@<(A+Cp z(s%^7!aVbotWpo}L*n%HFi3F2NMz_NE7n0aA-0Z5eDAmXjQK;Ou4%1Di7_;kkk$>` zzNSH?UdnVn?U z+wUeDo7cmdUQ@~ijFwPw_{wIkOqqx5is7p!Oa_>bF#r?LFZO`>E_3enE>ouzjY2pH zHPC8U%4?n)q2mMFrbotuHW_QZgb|XhUvX|$XJsBW)sb190+jeCc+@L71@pU>Np$S| z@|7G+9Elqn;kn&Zz~l71!w(6?jp&l!yq$~ql1XRz)-eTDvxY; z{-Dl>&c#qt;v<>x?kQ|Iz-WTZ|EUg+L;7J`ElS}!@@o0{9g2S%+^7e#mOo5Q>O@sU zA~Kk(N~57ZZV==ZYY#PQR({gW#+NcQ@vDck@k0U?G-2w$2YVw2yFjKyLYNeOIY|nt zs)P&vxbBpmuS5H;i!q%`OP8b`m)1z!H)w{oWfi;m3b~NNI1-W*9hBYXJ`o7Klo2mI zN?hHu82LlIuca#0iIQ;tL=>l8SI#M!x9r^j`?poz+UpDrrUWMlxyR<=RO`AP^*_fI zO&kUX9LN7B#CQnDeTejA8XIZ`Rq~2zRZv~SgG)5^eZYHKl|*sr{^nrSBcSsw7d?nz zO6ZOG zYFuEuy(leGL0|DO_H93`>6>$T80nPqSafT&W>7xxaQV{ecjtJ_gO?mA;u|~xhu+z zNnlf1vw`s??S0?ahZn)2-=?;`gU$`@Wr915%G~)bNs*nBJD!)xXH-;#fHw zXGW!q;?I_25yJ^7!tXg;{r=KjFD&Xr8S*DSS$Mm#z&a543sdu@0n-#R7HtT3Kb{*G zhj={OHxc{6BpyZorRqe4b?ry;_4Qk#GeFyciSZs7_pO!% zL&jNg^t0WiegENl#Z9x&wisq8*CBrjvAc*O+4$Uo^}H#!+s5Kmm(*u3v#xBjn!CmL`>^6*SMQ(l9T6YRY>a-ZbDfuqx@8OPZWs4oW{ ziPWclk=NE{VXL2VCN%a%UK@+!@L6@`c?#^Q8V0k`MlQFhXq^&qODDzJT24!*YYT=#s~<8alyfnux*wwk=od^0h(RA^8+| zXiI;@48>|@stz9G;*vuFz}Vdow*Q8opU_ZzY|Dp;oa^BD5HJzR4i1fqdQs*Y$BV+y z$+ga2#l$2tD98|zkt-(g3d@wS$eY5&)=dVcKDH6nrkId0)|CZ+ah74(uw3(BMnm+b zEndT0_EY@oty$xBW(scgKztqhyWqDI1-I(=H$ZPb7VvT~@Y2lVo~H`Gegj4%NTF8k zhfJ}T!fB}Fo1mJfu`j+T$hS7%O zYn+l7j%eI7FFa8=zd{XtOgfiYDgV?5;PoWU?%iPC#DFcwlx&({dkpU$PT2#H>~Cm` zn-tx}jJYMQX~Dip!+MneDj2HUazNZxlFk+*b?A)JLdfkgEISO%q>n{K^MP^w)}j{R zYskU}6)0;FsY+|cmpT63N*!Oj{u^tXgZOp(~}WM&HQA#N-k zAv#D915b9&`@x|0@|TOdi>$`|acFK47cX`%3Vb~AI&47c3N}NNv|PpZ3C3&rDdG?;Jv*}yI6s~bOy>-e!I>MzNG8^b9A_nh zV|zW!@d;b+d|sD0UuNq3>tzzGc$3bC_aj|Q&zB}4vkPGjrHqiMw=<7(QkabSIWhS-Xo{+f94B7RhC@A# zGIP?gb4d@Q5V`?%sJ&Q#q?ul|Wc}XiR~|HoON$TdaI>A9)v=w6)ZC&D5ILg&m=)cZ zi0qLwwdf!nMKD#d&j8nJ&A?20Rb=A=pp!+zTOi3iA`2XQVWY)#24@A}7GA9Wa-@lG zAL`M>p_6kSj2LumeM||%UV32mQE&la0=quMqDPRJe&1zjpw0da5{hn!()gM@fS=7o zOjBB>8^~*67=^)b2{kLBK#Q>(i2fZltVpy&6b8{u)09Z>i_HMb5X8|=#Cjui^juRz z{!{5%t6RlTn}*h|C6x|*l;`ZbLeTg^LAOPmq@<)IWonCq3uN)Sdk}LZFnb0~6M)FZ zfCtlfHUHD1zwrc?=$pu4jj7K8i*qw`Z>{NpB3@{@0nOm1x}QSybl_;^UqnZaN z5f|5Nx!57&eqdH)j80?t=KHULz7Bpg#)U22EeR^S-fceVPR+(>^Jku~L~V?I?9>G- zJs1mthff<2tJnG=X-u+*wf$h6iOSB32M<`Y(2$}vgflHFm=_p@9kve)SVeL;(+gVO z_DMQ>FQ@-nb7p#TBw21|(=3LZnY>XUCZBoG?5m(y7NryELd3f?0z4;zPxO?8U6!J_ z61M!cEce_*IACr*V2)Y}*9)9HmF`3@9GS|H;gq5p6qVKGFd?PF6vo)(yYrP9PB?9> z+J3>!0IkT5Jk2ZQXx5?WYi!j_W5lc|cCY#YHICvYXb>*jn*K$GdDIV?@6h7ifQFM{ zR)1R4zmS22XHr{%C&Sbri~c?rZkK5u^S{~+eSL?5nmQWm#!mlMKmL{^Hmbo1%h`@}q`ZMdpoUD=5vm~Mc;|L3a)%hX7c~90t3F2Bj}&M?-cD&2wgB3Y zr4OB0gFDm~fA$Q2KBp8miv6RgHYV$IYNiDk$y>Bp;}SF?PoH%d*x3NqPAEisxS&c= zv9$5&@VzZKDh0N-m{$|9!I`!E`1tcvHkWhWU$Du1ls|~ST%r*Kv|~;!&A`^a+x`W* z^ecOx12VPP^e*TPJpqxmFrD*RVi?o%&BweJREsCsM(%Kb!W_x`PP)!2R4QHB1MkO` zS{3;Ae;dzO(en;6HcC9hSWFPY8jg%cqMu%cTRw3G@TuHQS|^(CxmBI|P(oYv4R1i+ zxE4B#Om|wk_$RBcucU~+P46Vua)pyfGs~1h@J&kU>_D%T4T87+GXELr z1)P!cMmoaI^-76KANhvL_4tOuYhVeA4KlB#L%~LXUb*Wl+LoT!^522jkpXVb!+{*1 zNBH1^dKdUKB;*m+yUccTDDB};uDk1S$;cqNmDJ98i+7`rT&=Ts8|wUa*nV#CJ>tt%#x|Jz%)O>EG{YLtF5tOO?eDU$+GE#)qr)~>2X6xQ)USA>9C5hS{E z758UIc|zXaA`Bb?F_Atronguhs<=Yjgt$YtpsCH8o@ZLu%&Z;w)};kVbF;6NR_Np- zG{-}pdX+F~uHPk{`ue*`I)ee9U`J6cc?XiA61joPBW;G&ddz934qxNk7Ep8mtRy-U zFBX;f^}&G+exT*6pdPa&%PWhL9-=Ymzvdc};4jjDngg>jA2BNpO`+ zvKI-L!YzBZS)lMUmBKVPgPLiJib~FHRYr%Ax9HwZ;J6vj2d|?@Xg6P$Zzrxn2NR!;IN^?&Nz0b74r%zp_J+vcE0szJ@g;y;l2#Qmoo(zB`vu8Ysts>#PN zvDVaOxmLkt)NZ5$B{4$Z`*;M!BPP&4*?7pD($0P+jvwx=xW=yVa~nHATBYJ0Bf zbcaW?KUS9Si9A^PDsb+VKNW$6vQf0C{R1B6B@25D=u7yauIcOGz@H*d0w)9OOr4LC zEw+W82emk_DT&>4Yi$1Sg^-CJJjy3TWzZdql$28K{yHm6pZs;$1bZ@CWi-Gbo+SkHOy-fbtchH%oFkhLQT1c+5lA&PCcNf=M3` z=FgfxKtnU|-U<7xvwPkqb;+sf91fL5VT2QQn|!CdlIH1Jxav{cuy?FM>v}wMTQs~R zU@HMNVp4)kNEwxzZ76#q*~NwQoF9pe`Mgv>vv3U)AEhvidv(5EF%`$hPsUx}(oP%6 zZ1gjzh-_L>%HC>&b@n;EX?UhDu<^_w${&>-BA}oFp0Zy`8_rgr&U-3NHHY_CnajEA zFA({f7IF)>Yx0d^1kbuVWvan~Z6Bc;#d3U|9OPHv87}r2MJ6X~14U}Qo4Jl~x@&{V zv^k7NwAqdK0Gb(ic{Y9D`b#N;Sl|%nT8c6mnn8qjav6Jc7J^oCTb*nqI2Y$6qe3t0$3J(on7tNn^>(*S>tE1pE&waz@90uw~z zsPEf?yD#aCyNCcv7(G4VAO_@WSc-i{sh`9BW{C_%8ru*%CXpy(i?FCTbFlOaC^Ow| zV$vJ|P+lvyA%?2i=^)2ZY5mIYG^a^s_pR21Kz)>Fj$X%M)-kTW ziFMce%Hm$?;67sU_`Wt##fQ3oD&(Z*8#TEG@}g=O(Da1-fN2xR?w(qJdVH^*>b zBcygVE54kOmbB!A8wP;@y{{3;O-_xZ47<%A`4Us_8(Qb{{NOx$tuY5zMA~czQp<@h zveKc=g?hLgelv5%$HVsmr>w~)1NMIv==~7KDeoL}&Lx1w0T9-VVDay^i3rc`>eluw zh?+Wl1}YuciPbT5I#PMi02cMC4R<_p{Tl=Re5_}O7vRUJEHnog;P8l0mPAedebWzl zL^QTU2b^(fHPRX6>TyWk*=;#;ehLS((kgC8vd3@EQ!5Oo=KUx;jV;OFxi^n9+he}z znaWTBD3QARqLSKHcVL`sn?%%lz1@WfLBoRka)HbFRQhw!fAjxP4Q?fab8{swpUlWO zyRPMr%Y9H5svjg?kG0B0iHL|5#lffSBeZ;($hG+E^7mm0MPfzq|668n6M7>mp&-o5 zJW;=g!D0A?Zd0WH-K+0I$nmDY7hP77co@`av{}?on$*}yJ%vo|LGXVm4;rYbty6O= zk$*EVZldyqW3djX%sOO_6_9_Hq)1h)mmlY3u8*QAXo_*l3^2P6o41oT zJCtQCjw^52N=yF`uZJaAh3Z}ut4smle~HxxNHu2ZveeXvC#J04%H+PWw z6FJt={_{!tGQQ&Z^CCk>?~t_)mAm}}nqGPPI}!^mBYZ7=(Ky+tXWn`LQ@JmZr)c$0 zNJkH7B2z01xaqvP8~CabfdBVpTF_`I3PyAzh)x44f#Nq|%?45-P}&Y3oSF#zef9nv zh2R})PSLXYuL7Da8m}+>$+0YTQz;Ate0n{Mkylb#l;XLCJ$Q-ZatSG#4DH|0$;p=_ zV0{2-TlxzhP+>|;Z$a+Lau{Bvg zV^3zurcrX7QjCencF#GljVt{yPqS zbh>hIgjw84KlzFu2ZYpv)xheWV6romRw%&dR+%5o86-Zq&t6MzxfE;?ROkD!vny+5 zTk19cXHHqb8cgF;<%xZJiZGgo5qnq_NtH}Jdi&)}X)r3WG>i0r$v%IhSI6E%eH~Ni;#a&v zm>*{aHB;Z2eK8(-EEk~W&sWOZqZY&Z<6M%ZDubh{l|&m41*Y%fvN;fze)J6=X9A`= zt;eUK4*vW!sZ`HUdjA$?vVTv75N$Qr9xqJNnTv5O^+(+{we)|x$^j%`w~X2eEyyusN~E{DLUgziIPMrUDYoqOi%Y+x{l4h z4CH+WS#{G9?kn%VRK;TA>!9Y8O>qB~FP1RDdK=V5zy$7d4=a5V4v$(VJ58OmcKB|L zc}zY-pixW3Y@HN71U+Elta+OilM!{5KpXx_(GE+JDbR!S9{HZK?Juxh-{(Hk<^^((;;cOGS*xU6*?K2)xx7E6RBu!mMp#Cv-3gApbCA!M1RknR# zAT?dw;a58v^}&uqw)HdDRa!54w9Wm8*{iD}WR$z@Up#*P7W$9=SIbjFc-moM?~(Ia zA4)RHTUpH)hUO-u39nE8pyfRbrn@W9Ib2LA7sI_B34*sHk#VN{>EaGdM1cj-GzYQI zM9#uMRq@d_D7Z_RrXGe$-_9Y0TV~GXbf6I0wkD=9$*=S${|yuva9S>&(mhAbf=@cD zyE{&^1>H)ObPr;6hDEg1Z}KcQKkNVV5f=BSI6jx+6_BFHYgfuM8(fH0XeD;UK*_uA z_Q88pGsiQ}cx(Kn&Jd+Bx+hPCltxflBbZ`#VWN2Lb50BAFD+Dd=G+l>`Db+SM7&dW z`WBM%97ja_TXqK$vEoxyymzEEHqSI8`U(^tG`4tzM}7G$KH?vFAPaIVju^9b_ph~?)1{kH}9+mUSLQ^o#tb*L@y-9ZqBl9rAu~D_tfOhC+AMW1@7jy zsi$j6g)=Pp|F7z!ti}W9Y<(f=o>D7TU8!aZMj?XMzjtSnd;u@k&=Uu2gc&72w<8XI zIxK~@V5U2@IRW@AS}V0;2Jb283!+|e3)G|=^Kg1V(vG~HO=*w5*(5`Fu0xN%+WNA7 zD2lG{d*t#^&SuTU^th1Q2q^w^C3S9Ix5OqxFM%Kzkx-=Qz-6t+2vyo{*izz4UXQQ9 z%2WWRIIv&X^vTbi$_)K5@!1@pbKX~*?r?>s6H#t90YHd;vl^|~2QI^Tx9|r$>*2uI z-|5@3^Vi96g@ZFIEI@qexfy@O_u5B-0(`2d=}jcwzcZLSFfKhJW$iq9D)G9fZ{y4v z0Wb6ciMGYH|GKc*bqMBSaNxaPS+%60M-w`PppVZrO&^J(#^l!h4>-o~IsRd6QL70S z)kA;L{Owx3!3Rc)Qh+qG+@fiI^!Kd4R`Tht_Ja?OFtH%}a6}F=))obBOVb&H`tz}J z1H0E{wGqxoS~l zwmn@}DQ2(fI~c#=fMaZ#=&=+GsM2PYzvzUsowAR8he%-PEFT&6d;^q(TyS84!FV=6 zy0VA0m|(Ztm%=uDs(=YnM5Lx`8Nc}}4nDRQv4O8VqJq$q6I#1Warra@DnrICSXtSog ztU*~^_pvXVXFd+ozt8Qc}^Irs4y z{EHDWI?=_g3wa~DJt-e;s?J$S(HjnJMN8sbp~?=z)+jyLcnR|?4%S*>sqaW<`GT_o zbOen=TXWmXG-`6jA;p`R*jO*`+ypi9I+=i4 zSZZ02<6b7Q=^{^<7SA)bo{&Pmk5piMs`GU5lCNSVfrS58;f9Ovl;qB0Cf2S3LGr|< z*kX==USd_^_LR4bB0FO<8x*VrKW7~Nzlv%lu?pJa$+?B_n^t|yg_E5rv&*V~jz#6G zvsfR8ml=AMS(xrg?~gVdet60dl&Mx14VDCo)3L7X)vy#bop7lHN-;P|qI7R$f+z8f1xtjKAn zB2VyPZj*OS-MXc&7<8H`1%BWZXp#=s;r)>@`&*Q!MMC`>-W7_WV+jjoG*iOg6mc{& zs|TM|-jtooyf)LUDQ3#ai4dUz^q&Q{xNPj^CHcifv6as({4GkT@s~7E?K97K#2|5* zOstPrw0Y7Xx(@LR)HXyb%kSD}BAy-27wx4&o~J$x$1Dk5eTmWb#z-ZU{cFp(mq+~~ zd44%F9efuwMg{+#fydhk;lIb*dh);(Ls%q`-$E|plQ@Pj!*^fg?@W&gVTfkG5zG~< z)FyP!l>n#?!M}E<=Y_0ioA+==mi1kH=J%;^ONm@=vxwf+-#I#0Kl+i}5R7n#$Xr8_ zJWr`NKhq>4T3$Px!#KkFG{2(X%F%X9_h+@(c^oAB<@sHhV)cDz&bJ6@#;uj=jYAjv zM9#i*N;36IPQLST4Q*mWQu?KG(wh?pcNkhWv|OMOG*R))w%iiKyA+K72PsQ1*$D6Z z|C}}GIh>cu>QF#gf^n(bNLChBGvglg8NiBre@eDcQx2P8bg^Oxh`PqZ*=1+817%L~ zy;e6!SWzN%`|oTUn-68zSq4!3=Q~i6i-Hdze*yQa)Nt)1b}?$%W+--Z0XUC#jr*;&ViiK858_lZDJP z6gE~=dsS(IC&w+PS9uy&!(RoR1gv8#Na%jpBeZv|Bb34P0BqBsPg$V=hC`NniSr%d zF`?QeM>1HRjwvJj&fr-JnDiu0aNUjGjl&IzB%5>}D)6C1ZTZttzqYSNLpCV-K%JJCi**eV_!lf>&wJ?a6GiAc@*HI1xp84Lyx#HR-Xlx_ z&c``0YA?7;kV^T3fvjqn^bD_V_*;Q(t0>OdOK=w>x{a10t2hiRa8N3_TK+)RbVbxN zFgt|*`?$p;tXJZ>-yyRHM8tpnVCOeg>mK<3c@1V1O!@?pL( zOp0zin;tUxCzacZZ&1!nHGI@=z;jlGTbl$GD)3K+4G}3R}m-WSjwf_e7zW$hwX!=9~H9^M^UpM%zP;g4zzPIN~T8U;L%ju z*F$s!HzSFJPCvf-o=ubpH=>oLbU?u@Nt9k-q*+!k#^!=)hsE43bN0!O+IgAp_ym1^r zj){@?AJGUv2wOt3?~9-!=?mI|k)<3QZkU#`%IlK;2RWLvy2}se_m-NDY|CQJ(8k2x z?7u%mGih3@!jiH?j7V|4;fypR!!Ix$c|i_PuLLzibWRPazLw+N-lTKo+y68KH-p1+ zK3e)w+ICi--(26Rw>KYJ*{*ehLtcJ3Z%_IIiym zK$et{hJ}crhp7jq65%!+E~)wO&Z^J?AstZ=DTcQn6t1)(9(Bmua}S7LC{1+Iok$v) zDGz8af|dG<6?H;%S)Qqip(2FUq5&sH*W7m+V@<`xCBzzEI*A*&G|}qNRow=_O@(PX;7}CWS{hGVy0iLE|cV( z9l%}#mW8y++CAQuAC@MNTG0fVf$aFr7{mxrf|~v_j_r;;%f6@vl8mFKDZ?rof52k? z>=o)*87T#qD7D>u%tr9_+;!bD=g3;!^4p*+3$ifTr|rSkZ`@#NU0bv!5&Gvpi(cr< z#FmT*$xuqSywfd4L=(PdJEx;*W){h040X_UM4{2#`{euw)#~yaNZl_~jM;g%q4?Gp z0|UMx!80kwL*+nw^GdKl#SDUA&8hyE3I7%aX|tACSY2GP671AvTTr|k845dI)yb}C zmqYYuZO}dLqh$QpL6fu#pA$C~+eHri8s0aYHx&}#n@GDQ-W>`X3{0TO_(Q5bzWrBjolgqb(wE~YnKg>mjf;5 z5Q4_fV3AR702N^rMK-xPL>))5XUSS`Yguk*cDb>jN!5~oPJ(!GsPZgKcY@hpb+mR^ z?axBmoyQtRRb)I2XdDu*C9K8TKfGyK%9OwI472j`e#>mot*$eV4Ab#sW91|zCRI1Q zt(SAW4Yzt)I2st;@aCQ?Q#`?6_l_C0faW_yb@a{V_$5EZiE^ zNtGc8U~^^s7yY!w!Nux}f=1`q?$NCH8|d@sL}`Q#w0?+dWYCj*NNZ+Xevu|o&`QnS z1IY)8giorsiI_S9UO`V8GGSP)@Shkd^zeu2?}Iitaz8J+8tH<9$1zG_azBTuohFn>H(i9H37(E^m@zo1VnO5vMd|jjlZs0C8Zj{)wS9S$WIG2TEu^KI2N)K_KaYe#;M{ zu>H5-UMWs6N(zH|vUd0s1f2{z{&8n;-Qmd7>H#Lg8B?6i(qX;t-R&~s%>`pkxjW!E z(c9tdwhjeyVgmCLHjG@+eBResuDNjLb?p;${}!!Y7vP+&Qpb^#Z1Ln|M$FwV_zAcW zT#N`$Wn0BkYT{6MkrfciE`p4*L5&iNuYve_T=pkTF{_iFk3L6FibsBreLf4pF_oCS zz>Cc+CP6Zf`1q@O;deYKFx~iHank>R9^v+VNph7eI++#t`tz5~rkbM@rO1N-w_VOA zLcgX-{_Bw4dK6UYs~8l!}`gWpO?4w7i$ z@5kUtIfWsFA9aI@j{W%sjdM;71IVAfF~kx~h1Vn@=6i@L;8&bhst+Y6*Cavhq$dmA znh24n5V1}1qdQ#X0WKmatq_y{g_GpV$)?2TYOaD5u-xg?_ia(h|DojZeX3=TWc41V z|6KjgeY8YyT@^Z5AZtJaPDiVaG|d=F9d9!pw=)Dq;H=AS;mNq(__NqJr5T}Yl2}66 za%kiWJ|TaHj7%S*wK(GB5VR6JFc2I42jWL~Y{P<3WBsG(6Y^bd&pGC;eaY1PohXw) zHhe(X^hO6PbMzRi{D=PvbZyZrlEQX9mJ?$mj-W!Y0!#$0L$oY9OPY@mv(Vk&l5%Zh z-WW=JDQyy!FnB%Y@50dx_;5ZBr}*W6o_I!6y+2x~H%2Lfb<|l=;xUlAa$b>>7SbXG zN}YP|&oR&Gl<%3}N!%w$B+0Flpp%f53HkB#D^B5+tTO(kUn0j>4_o|-1)Xf~Exm}@ zZI5vaWu&&zT|rDX*WE#NB32C#V6*Svu2xj~Bri$Y@qVH*gR#Ujfw%-(kvuOF!^8tG z&@w^&NulUmk7^A8VMRVMtgtbHz&i|q*YF?b)@i|GIkZ@iID@1MqPg>qgH41AGT~FcUNwJ zrI&dwuSN=PS6g&b?yRZ_fksn!@)DU<=fxkuajGsw;)ct~gHCLb9{kuOF8&H`qgX_5!lS$7VLO(eIgz*-Yc>Pr^2aQ?`dudOj!5|erNA-s^Xr&g9hwL9JVTXwmJx_;P z@bA?PKYds^8|s+B;@OQQ-0MJf6pxD6UTi#f60F(t+q`>B>np87BKW3b3HIOnLdRBu zhx<}vD8kymH5T;f+v9;83y4RmwLDnUWVpz z9!o~`a)py(h;nv(9d#-EQ@a)y#FL40_m(9D^l0NqEI9RPV z`oBepA4wIoWg^$HG@)*IycKhNvYKOHekC{hz_Ma9xKmBqKA@QJz~KLdmJQRlOs z2vblI58%yX2f+)!{~{~XYN&zR|lWZ(90AOg=BtiG0Fi(V0yC(c7I&GQX^1mY3<*bH{KY)K0>fy|ZsBnp6 z+qORut15oC$?8qENXD{YiHWASG zmiff2lt9m!%H9a7CKG_&9ta!T%Jog}xPF8mO?df09{N4zOh;6s6`#jHx2NY^U2HZ= zON?8D5|=7v&NH7$$nJ2&UYIYHOZ@&tZ(wC+7k8OiF?7t-pP8u4$LtW>>BREXx)b_m zw`dsMF9^6EE?#1?LG$EIc7AsYs>U+lq!%rOB8HIl{0X_X{hj-@6zb;S)+vwxQ)+)=|l2jUX<1I+B{IlQ$4wg6hDW^m_^2Y*CU%R zn}H8z^1W7CLm_^aI%eW`@+xG#jiuH=rWiOnwCPzVZi9I|)>_HB zE!&_-o4w@tq#%ZI=oI8GsXmAWqwdMKLVolnmUgH>XgB=$ueLakATiyi9N2iU$Htqp zD>t}UgX|in?6(V*UF#$*5|ALB27+6}$Gpmw$lM?Gjm?Iz;|32-5bvyz;#~|$pXo=y z3BGOx+v+FZJdw4c4)^jIhWp(QwJR4IF$@*eB@x^C0-~CGJYY?DNdMChN0H1yROd8# zy6G-OCrj8-K_vWK^Hi3~<(5qT708>w%S&DkX_rFdUuw@39~TaVYotTj`D3mCA02bE zRyy{{S?71atJ~uRg6vL9LvvZpPZ2U_hfr%be4Pr7-*Kz7yP-3ZT*>Q_ArU6~aJx|9 zKfz}=z`>W<+W^uX%)oQalfag{3Z`9qQ9CoW- zL!V{EE^)m#CW*-XfHx18PGcS?$9;=eMq7x$XZ-j&*_=%f^sJ)IMoyX7|2*399yjX- zL7q{_q<+Jns1`}zl=9G~M)s85HMPMg@HhQZ2MONw9Kgx;6S{rBNq9beK23fir%Y3W zEJ{`92Q{`>xunJ{;d{0dx1CBPg7Fy}wif^W%CB>Tk=mvAltYm~3IK^zDWI7T7&swp zTf=H)1FK6;EbYhufi%kIjTvx>f>QJ^wfY=MPCQk)RM)IewOsp3Wi-thc1amc})_MsS zt0s;WJW!xkkyC&m@zb`^pphj?lAKn=BEe38=9~=Y!;<9^vzLaZ;DUKn+-HiHnfJh% zqOSaJJqSYVukh+pzYvWQ0P#;Vpn@Kz$`+N`bT#WB87i=>Kk44Su8|*_zAYrFqX_+| z7_s-Y#S7o*T#cm99rSTZEdCuvZJAqWjuQpR9CyJW*y#m1C{ROITRRha(&JTf>$hc7 zV@!{weOU-*Er(ouq6W^aR5>DlYOYYx(oTisi1|OW&Odm$l-gQ$7QlBierq;=^o#rc z&$}csFJxD6YUXx0f=U+pVDuLc#gL6)676z?{nW{E%8U(uCPKbtpzin=wH2|a#~QTU z2We@_u(oXygh#3XwXFm8uM*nvjhC}BBk}2K@5@}=%xvQtITVVA_bK3bYK~WcN@%_v zEw`?fSTTpzOjXs3mqe}iVBNfY`Vi2AqE8&sQATK(9C`;VE4BHpitfkt?0#W9X>oL? zr%R0)8Gl6FQ|Kh*`#}YMR|tbG8ket3I)zB``{8G6qA;?OP&cN_%3+abz>D*GgRDPv zp!hRkDf%>8f&tyh^D_3eCzHWffwrt2z%B;<_$eApl3<=l*j{pUBJ5w$O41k^7BxMy zP#%>pt27cwaL^Z>sT>u2AgkIB|LInt@Y(~c0W6F64X^-6QXTh2)i#;u}#8zIN$O2y6U!x^~=kLgI9kVD~ zJ9L=V54Yu4wk*=V;aXH#zK8=9HaZqv;#j&QSk9Y?-#bGh5Wdp^ucs#-TZtp$!t(XV zU;v}y9RppO9ZxL!7||Rs$@+hfRZnYf41#kUDorlw7Yt42b|{7vUqT>@?Pg0PcX#dy zN5n%Q(Hem7|u-<(Mcg!T>xQKbyGeja4ZI=h1hXw|QW|SnlRy)E=NvrU$0+`qVi7W95 zEz6HsWG6ITB9^s2%=-P!uRSuTB+Y?NJGfl%mkdN5Z3??uf=-30>Gnv>9T_#n=+KsaZ)NNRRXJiU2t6co(6e-xm&yewy*~rh(Waqu zgvQv3iq8=DoURp^BBO*zj#@G^3~l=#@0-+vT_^_41t93jvo-HrWRCW4(i^L9 z^<6lUXCNo_penQqb`8h=T96IP6LSQTIkZ-wxTzJyo_8Q+iWoN!M=|zXQYY1m$V}Rq zN3e(M;@@$fjq}!XzU~VC@#TYVC$w)60(D(M{kLA1 zM4x~x;HlyQ)d7>dgh;Z|K}C_emZKKv5mv7MfJ_<$`w;X~CAb7V>uLY=?YZhB>D#%Y zas;;p#k{0SX47FyFX}!Mq7r+}If@hpq+Q~eeNJ9KS5y5E9aE_1-Z-^UK(t}*PKf=j zdeiQL5GdnVokD^3HYKxK@TZgs`oSvIJved@gx76$64OEvJW_g!dqJ_a5n$Uwx@3H6aX-)jSAXo?J zf*m@SUX#r;@iCzxaFaZEJO2_deyJ^fH)0Hc$ESSNKbVafNQ^4edPax&r9l=N0VDZ7 zSz1KE`6+hJp)1#fKw+hzz>Glx^x&lvIFAbmv+W>Qs14G3Ab-Nb=8sy7L|PtVql5+i zxY0(^V5^2UVy`E~pw)^`Ss_cEO0K&HBu%n1P=A0zK*BhDm zL0Qhel{f_#KI$G@yo`r`Bw?YHZ$=P1khpvI_&*iON1!A~OjU zae!2}qFR~5JjSIN!eRfX;gaA1l~M!RGt~X}u}DM?Sl_s{NeaB|gfK)zER98aRZ4Ej zt0sAR`HV-XTADMJLIVFtH9Fuk*-VNdX7J72o>ms2EUg-OLGKF5Lx|213O8gVsBc3V z?I@ZK$6@<19AC!=gP+FKXkWr`qFL+s;TRo#} zLQkRLa=Pyu&kO5;`#q>5ef=EWMda+H?wEZr&h<|GVr2+lF{qwBjPu9t5#~t}YM6vR%h8%dZHd zYLDGGf|@S9c$~$Z>Y(xCsz6O>Pgvk6hc&M$5K~bpS}{BnB{lo2is-bYUksMLcIAdx zU%8)$@Y9tp^`?I8?w~%InS6dJDl*-i{@bxB4IN!LKsvdYn z;QWXrt_ZZ4rnFs^j<3^c{G-BtPMhJ9xT8;b?;hSslf5R_LyoAP*vHU|s0Y1mr z2-|n|3(h;LiNY4*i^D9YoVMc}t&pTEL|{>E2>iTCjf?sN{^3i5XxM>H8e zW>83v(3}FpX}gvWDLZ16C=R%w+`XI|;@ogc!MN$pi-b@YQ`d>x{Hp2LkPgY!zug9A zWC7Me@OhWQuW&9P$mjQ5_*hr(N?HBrHJM%`RGAdHeaqOy{o29gVUh$W7xy96$G;PS z>V2kOK~wRg`FJOyj7+XE4Idwr8g(WvyPq;AUOP?MBL&Vv%if?)YgVg~zDC^J-jn^e z_qpt9DY5ZZwX#d+Ul_f}-L9etU0ORnJF(xurAR_&5AjKW4Mk#K;oDv?C+{eW2l2+y zYdJI^8?t8Cqt`~fx{~LjXn|R2Ip7H5v1jY{Qo%h{A4?A{8!V~4_g&pP{6sU%v4SSEM0ze zGYok3s5ys*@ylR|^k}Nx&P^gPOWh{BoiN788Qeic`84ZBCg}c?l3%|KJ|ru=92qc- z7)zXsrr%`nP=13D4zS!$&CU4Zatm)7w4MeRKZZVtKs}0`acWIE1XoNu5$S z;l+o$F@*J&nS&*H!nM1`kU{R_iWsrvHZKUo?xt*A(p?s*Qs5QG!);ql+7uP}Hn+VM z8!qOotH_67C(Y#1;E3etIcf3hVxITIXc59=d37=w0TtSKst<*I%heq@qOrmAg!1T* z;CDoAo~M=E3U*C1l(mo6Sp(zGu{{xa(?3cw+=(0Q|Di4G-h5YtL|zq(cJIt_-)npU!1zEA&l^=Y@FT^R-XkuX&SX zj3S5qVd%nT)E+@NI6aBgP#pZ8X`qevSeiYMA_P!jFLWrq6XO!IqIZ#)F}f-BoX!Ni zS8B@K85#)}!^Cgq4oD7;ukJ$^;GG~aXfca~dyGZ^+8c@ls!c+?tF$?TSX(O&J|cL< zvX`&d_e2`aM(f7-+30fV>)#={-f^Zi=6bt4WQ@e6#D}&(RnZ-Wb?wtc4$4rNI{n#n zt_dm`sgZKJpcvqZI94;6iwIJtdCQ#t;|o$UC%L<2S1W0AE!Q6le{MU89F%8KPoZ#n zASYI5Ca9_UTk-_u zkA+UnFUhNr@t>F*iG-w8F50`$|LT6Bx79zOMhL!FbDRraSA)dGBPR5;IeJ}M;~a(u zZz~0u`<+JedTrT_xG$+Q*>@%55gtftSy*1a!;sZ?C?yZeh)QDjnlKL#*b9(~{dzTl zDy!EZ4CUn|<|5YsNX7l{li)MF1i$>quT;FLXf3%|A|MkJ&Bc@iXVO4}?syk@*g~>Z!ndV?nGd3zQF~1YN@z z)kWbedmiXky)ei|?m-BPsxi|pU7z6KynDHPls^k(o3+l?XH@1*f2ycZn3D*6&iwIk zdT8~F7PQb?>e?u5ZAI;F{P5Bf_WM5gK=`X|yPn!Z%$rnCPZYviFs&i0dg4)riQnvT z_S$NDXgD`=EJ536X@~mt342)dX@eU?O3=ai8Dv#Yld>K31b%;W)0BI*$bYhW2aP&g zDJJJVW{EZUem0I=bp0DXs1{QUDcDDDagLQP(PwV>Jh$Fa5#q2qycGLomcp@ZuQ8BU zr?aoo$K`KVgWt=av2&^Qn!DTE`srsv*TB7fMM=-g&s4;wSW^)Y%hrHTsWNp-@}p>| zcew*C${)n$sNPyZ|GVxXgN5cMB9CVxS#zEHm5?4Is`=qUGe}RqbdQI2SwJugvsw?_ z<$rwbFr&G|;gsaXY48=Xj_vUGf4@S;Om4{8R`d6O{{h{+XX617-Jvimu!IEp*Iuxx zv9-9d8|r#=JGP^*`aWV-y(uFAM?CPYW)QAW9zb|jScLg@&kD@zr8_N%H*FP-_yu$9 zty*T#TU;cq>~%FUjo)30CxrH*LTzb_r{$|&^ie#>1Tq$eYh=McXl71iy=a~+KGN!Y zZCl9plFJ_ySh_yyQOs{`U|C)fMBp<8c3C9S6Fwzd_@Ux5JtDS&(cibs3Pqu4P9f8{ zx{?e$F!?nRK#5NZ%CU$=Cya4eE64FreciMV>4_vj=OsIIXZ9f#@?jz;x8l1Fjky+V zcI5^vpHlzBbKn4CDxCG~rk8eDE->`4`nV&d?6RX!&iklFJD&YM*46nWnDFXDwKld2 z!837!AfsY4NkS(`{}sVwM^OVk`c@Jgwx){sHR}VicX1C3Hlm8D$lMS1ySRhSs!lx! z?YzEXV<)0G@)$<o-l%WOWl_ ztrR>tS)3`|zy0C!yYS+(u@Z;n=)h2YjXj&6LXE_Mfq&pJ`B^mr^5G|Ab0jx1SV7iQ zzjTACLhVyny_d0hU0%G=ZFX|<`?=er9{A|VV~@F?VQOtxj_ph0BOnsEoX_Xk)T`23n5aSFq%}!tYG!j98w7RDk6)0dhI&$u9Xg>gmKWA${(`iHV zU3jeF%BYmnZiGW_o@wspSMi`^K_^rRKd%iCI0QO+V7*Aj9|lDhRRAg ztUuDm0JUjr)r&xpRwW@(>}D3G%m+)+uxuU5d+R=%rhdN}Qq;~k2~VKTlUf%IO^9hQ zyAxk*yd%55X&?h1RCK~L46iUa3M&SFJ-_enpgVz04a+G+68Uz_d|&8zfwYn22pzLB z-l?f=`8^sCn8v(aXnO~jfqqM_E(YnN9A~voN=XR3u78@84NA-4s`IQg){E=0tR$z| zDl2PJfzTN=S_RVtqW}}IAs;#3`T+j|Gm2kn$`NsrcdqLJP=AfaVW4lMBMMn?`31hi)q+awyTcMjAT)IpiPD^yRA5zroZ6apL^^Y@VIFR7)J;dcyaQ^C7d4 zBw=!uYnmzeFZD;R;jte%>d|%l?t)d3KPC|^7*)h)6kYGM&D*C|#ajQ1yl;d&^RHk} z84`?JKV_QFZr6JDrzJh&6FxX};3rd4oILApcE-$Cd-+oBi1H{5j{?dbBZ#?T4ka4- zQj;9S|Hx2R_gmHp(%)+t>9ZtK1U{O`x|H^##$3UVFV`Cs$d4hH)BTSZS9=yo5soTg zqDi-WPF{L`C&FuPE7G`wuFsHS4stA;fOyj4lN~7yf&Cg4O{4HyhJf(S#SingdO??~3>1W|wI)ckh zv46>9l`?CRRz^m4Gs$TuusaQ{_I|}2Ud%0(**Egqg&7>nDk-1`NNLNE$S3f-Q#IAi za>;5ru&>7hRYAS<#VsOcWlfV3&t{o6Vd{pILoy*HTiOZ%kY=gXlZU~gPss>VoRAr* zA2DVm^d-HxbI*3ehwP3V;%jJTL=sf~V~V&c8W4(RAbwUWY>w7Fmz2}3NZeE3z2FL( zcY-Geilb!Aaj^s*m??~y-v~SyIH*YxEmd9(dK?icTyGHC$G3j?=)aJxWJq9N zD`g~&KqM`dc=#68MV8<(b{lmSXIT68Tg4HTBLAA(V3guERYq1N$2Ss2- zKu@LSVAR2W`q9_CH*El+3XmT#AX796m+z*#3gbRKwCnFF6NwqGG*R@*a~w4IHs$PZ z)?FEVwxx_^w|PPk|6O3IQM}lNG&=YKfnPZM?#QA~Xa&&iiIAFn=9@1b0T8j}H$+Sk zW$>35jP>%uDTQRB*7Ah3wf}@j)OZ$bUp=K~V$D|^zG{t-$9VJvSW0m%C7dk_Uh%LT zPO@(iX8)Yc2Gi;&EovL;5YRfk(D0XID3GP!0a^fP>X%@BZ_aUQl+X8!j1Xm+O~zH{ zo6M55dct@JS9!|VyhL<#ZJc$)%ull(ZPHaTT;bD($GXU{6V2X@XKE;;hua~2n* zz{N*+8=vC4A&pIjEhE9YWhqhGw#qwlu z0W1p9fEOEyUA8ycc`v5Tc~5Q#z692%Nz{gaT|#fZ^eunv?`Q9o)lh!YXKy-~I;-NZ zIbAAAQHVJyna!A}Q;CYO#17doSZ=%mX=r%QfE^7S745VWPXLli5>hK6Y_^xtn)=SJ zeAJ^yvE$?f36_VQYlrU=FvRv6bEZFn56`K3#`g9A{?F>&$o!&VD-%f{C}z8k*Zui% z6(J^Jk^(s7W>RA~8AAJC<(V_BS0%&9BA&E2ai5WaD)v|VdtFr9-{}Gd61rM-@$h-r zSO$57Lil&$AHrZW1kxt^$#(X~19cLfFjA!(XLlGs*FTkM*IqnNM&$gKv3_j{P%(S= zm)r+&6Y{m3*TWKJ?dvg`V(BeRKkVsLg#qcPBf7G$Jyk-&^nmZ@*q&4OQ&_lG74HL$ z)|6|auLQu-<-u>zw8BV^^)?htqTNw4?PDEHMIYmoLz7QIHzjsaL52O))<&tHc z6?52Vgx6W|myc>%%^6UMR{~AOLX(div9PB_DaHwMi(1+dG~P|!&pa_aJBq}K&Y_kp zFA;8!VNfSAb(j9_i1Fm8)aY++jQiI+`tdn1Q!!1AGb}H5*%DnZ zM=sdxfIw|3S_a#q=Qvt6R@e9o%4!S*1)gkn-gB`fo{|W?ls#>W2v~nqtS>d#7e z%D5z;{5s7U9w#lGpl-UKT)Z&B@eZV)XWQI%sbYf9+ zNj7px5%+;^0+JEwp-D%QERW4dOUvcm0>1FcMOWi9JN!wI)UBz>-M zUva>D&u;cy;Xi2prNgIu_2M8NHF|SH;~}ga(;ZSSJ`HVrL46jl2YwZo>vyF}CmMOe zf#Oh%81 zhYWSmT+3>OvAYd7oxL&bv9wbHa3@&qEa3gVpBUUzmZ2x3s%Bejj`XKXdh;~}O;s>e z<&Qu05H}G@`Y68w(?CWTAAr}OCk{$(_v@W_G*7NQ8-CKvjW%rE=)5}zYPlxf8mwqz0_dc1m50n|hpVaV)!%6TNK2 zs+$K^o`OD~F}x@P&c20fDPj)lJHPO#sCY>pNJgr2+qpH?xUSxaM~w!k_%93`HEkr{ zbbezLxLUAkdd!LWGcA6nP&B337hK0EQ8-my^4sfl9rA75Y+wy;YPNQv@-Sby)8y?Q z1pLQgedjN&vOdTz)P>4xe@&U52ca}Y48}$n382rTO%pe9kB}%R7QF@=n@`d(fFtM^ zi3r)eGC7?ItvTkE`ss!xlCMkT8#lkoCADx_^b0tSZ>=OdF_CfAa9L)4S=w=EW5pDy z{|ix1`%2wWu>JCZY33g>7U^hHLw+XXiiH!BJF#Na zDw2EZ2}ScxRgV=VtDgB#ya7W&Z$}guB)x9E<1<r0J&I@D z+=+W4Z8}3YH+_p+~(iFMR&@gA{27?+T|k4T8hr$p=3bBdEzh_XXC(L?J&uTuu{+K*Z|+U&>+TZeOzU zF++mgwkbh*vW6NNL(L?n03JG&nr?YfNsQAPfkA*-rtAJPP|2k+mp}MXE0TaD?wbhi zk@g^yGE&oZ0ANr59}6@?Q6BdePJ1*nDfv^tG0Q8_l{0k@6S-USHd$N=ZFfrMYhTgn zYc;`sUNG#7$op-z0*oDoXm?q;v7Q2i{T6+0fo~dEObM1s%Hnzhu0L;yzQR71YOUOe zE*!eCZu|euNjc5tu9XL8_f9@{(^}NS0ClaZ2avM6c!?@`_`$n%P>Ks?nSOSgQc~s% ze#jCjd;}WdfE5mcn!ng~mW)Wp_s0?MsPbTAGM3CC5Eij}e7jrih zgfxj>V8V zSB6!&b!)q&L!~F;CyE~V(NO!~c;JM!SoX?AY!mMYE zG4FAYnCn8pjQ--E(u`8ifQK}JGF*g`0OF*f&Y|*u#A$aYTK|dMgA9CA(V~Fj;f#b+ z{TtP*ZQ%x!?f#7NdmrSwi1Hrsp|E<3YK3<1NF=pnaI-s&oDOW`5u-s)O&+!0oaE>- zU1X{0Wy+|)zKkR7F1+ZpCE5t-fD@;M3`@Vr+XQ!^7m(^VxcDyLM%` znE3{20E%MshRq;%;*i!dNKib8#A6$M)#qj{mBS{vQ$U_U-U`6*_tn7z?^#E=gZ?T$ zo!Y}aLU(c+N3L^)nXF)VX(Drgx#So5n6OU9 z^11J8Vn!jjpBXs_FZNc$J{8n1eGahEB`j^{Mj@>$=Yt#$bf#Odvaedq1gcmaDx^wI zr1k~{O}75*zP~z%PfiZWuxmy7z<>IN3GxVd-U#Z!#lvkU*w=+XdlbgOZkAE*|1nFj z(0H?nj@T0#pI>LhDT0@a*NXa1Js_dDPy5zCe5jI{yIL%KiAWR=Np}B?@Ql141JTS` z9E^LNcH2ND>~pfd;|I$OJ;hebzh7p;<{YvV)sR3!zW8pV0N-y+Eiw4Mais`*`s#=M zY9$!o?M?JMM3J$~1j+^yJp{IStRCe0moW)h# zNl`D9vzJreEU0XDzdT+`=iCsB)pR=Uzq(e<8dAPX#N12^EOt{LCfP@=@zBw<@Y>xF zMc}U$PYo?g(RbRfip$XV|AxdpkkG{|kT7=b{zc*OEM(06ILY4lTlK)c9eenvX#Zw} zKd@yQlP2e~Ml9iU%F3=(j=y;ac*+W}^AtXS=3}N2bA0zlEJ0QN@3NFAU;&~-@OdF< zYFmlx{>k_8*bUO7uBjgk24eyLel@Px_2i33o(7UWzKIojZg!0#E(-C5wT@V8%8e+i zd0b}upUm8zPyBAsCr2G$>7^*)ms7ne1~Z}a*>U3ye?9UpHbeI|xNhhva*8N^h+>TN zSl1eNvwf(}-eM5GDpOzKdEM6(3~CCs(;y1F{$=w`PJ~$$R!9^#qxGyg)1^|#epXI z#z4ju!7G0GMD&6Gqt}B|j^fC1mL6)AUko%**IN*3W*{XVXZk_jr|kJ%5d?x;Riz)j zzHT@340JWC@!qHYg|6WF$=IA-;dNQHer4T%@Gy?vqv7Lg_>C39I#3!m*u@- z+0ZP-ipeJdS~dS#4Py^#o2k@m{Nibl*;nREl~r zXCc?bOX5YppSUHlR}{1nB`>-ScY@;P5{IyjKW5X6HrLi8~HcJBOh{Qk|*CBFf8g5y>rdE7UoA zQSaj@rUI5f(R{1u!`Whw8@)0a+i=9*Mu1ai)F*oa3^<>A{jbDmbPqt9eJjqK3o{bB zGv6}r`z~5q+EVwuwqqJ5=A6ry*~D|%^TDMsTwmIut(yn4ykMYb_#`!@G;wF%Kcj}u zuFn}&0)*#A$~vo=0N$|4vcC5n%Lj#{1s5DF&MQZ1u0PhOxUPmgbsNC*wHG6QvKFE) z4?7Mtd_GTUK5jjTOG@Hc{?|7L83pAmsmdD;A0PjAmkUygE$SR;2-o2K0_y$))J1o{ z691{UWZu8`8o5lJ)wq~0KY7@Nu(ylwOHSPUJU~YeRoSpBmQ4S$gPVOvSXI#>(~~90j{UGIe;ZZqM=Kr+TD`w&lZ*?Y4R2d4t#NIO3q)Tv;-j~s z7DcKm+&x(fskIowN|XIStINT+{i2i*_Dj!>+r<_ZiZQ@;~EWbV=KpMBIROp`IC&1bN^e@bCQmTMtt`u%54C_SM0bfsun}j zk40hbe1G!t3%4)vh#{z_Qs2Iy(bH}4etR1=vu-*}aT{QJ6aw($mWq_{>zx6zgrOGNBzXWmdEH9f5}U`&+MliPyy;h74% zSdic*D1h26x!Vc9#yz3i-k2XK3Wd*nL(sbZ6H%@!DO;2ATtse?I+uSAg#L~7 zJ|r9*WBkIcguE%s%pc(I{~QOpYe`CFy{c87;>kYmlaeD9IK$zjcY@c><^er^nB_5r z|Cwohh<1$`g}CbX@&L88vSJ0v-P~(iWEDjbk_#6GMua~qY4PBNNaF#lCF&NzgkW18 zARlf97n7=dFR95C9lJ?|q5N@n*z21_NYk(zw1qQ7U%ufx>ctXQ2z%+)S!Do@qFj{@ zHpaVzch3aj_!NPCg7eh2XF8nR_yvL1*Zap-KPeQU{_k|3>BOYDFWhCc95(pAT`-bL zdV0cl2M1YP`Rj+QSZ03*7oI*4q130$F&`IQkBf?^`NI1=fn3`vv9CegRh0u#%u;Wj zgta&r4_8|-UvB(f5Yi0?QSW_Peg&YM{xEz(zPlrH`eE>aV;Btc>Yge@1I_v9j(weF z4K!*k{xO~C69_zi2%=}vR-u{)Z{olK$MKU*@d?+*r#~^6in3^gs^KjNQKQ7Q-{)4wGRG`u!C@h?7|MahxWmCRbRbFT9-SVU(j{(Q+JL~RSt_;|kn z>2Fvth;$m~8E{6x5M9u7ipIddpHArvT3%lMN#%JfSJdDK+aTt{1{l6qW*HR|{f6J^ zBX!S$AHt^zgg({F@NS0*43eUOt8cOIE}dO(D&-gJZ0btUN;0d7E_PQ73kS5L7g+lW zX@n-(jjc9xMpQI#v3B33r+90K z9E08DPZ8PNCPw^JEKrZ1-kNfD>y#s6vB0|W#7{D@w%Kv=)`|C&e>NXU#ooT^b5~gs z8hJuuqQleGLP24nSSe?*bSVX^b7*x-w_rrPB_4n1xY~6&`CIyD=Iy(ZE|JBY?+F!PAfALH-<$L_ zxfE-%wks4d(RYXEQ^kcOJJE^A1)+CD7jv#}`noqB9kOzMQHFK4ub~`a$vVPGw8kVh z+0~kIIypn?`YB-C@Ghnc`f`*u8k)Vt8%y;9=TugwuxNP|Xp!TCGd6bJMb!E-A#kJj zcsJoEp{AfBMd6X9UwF0L`oZE|*WFjW~gFwrJb?o+26slhlEG<6L z&uTQ0G5M=x^my<#>KUwGui>1+WC3NwWxc!bNlkGT5`v9kZ>zkY8r7XM0TOv}xv>Z~ zQ|ql~xtZ0}zm05mxqowe{PQFZsRrS?wCkEvP z9Rw$UH2}F4{yvE2S`T}E_FZ*d0WBlatu=BX77SBCfF>g*Z(rRKxw{2OqnY`(bV_&K z!BfJaHn}j>2`7hg_9X%fA)y#zSIG3Hhjl}9D(c$^)HYi_0hmDj#r7?z`&I=sw__^~ z?cWV-T6+4NC`G^Phg43dP7Le_c*k7=f|#GwVkPKB;+uFRH`AM@8CUVX;7 z;0o(kE=%=@yQTe1uZZ3M^fA*UdWFyjI67XORo-|b&sZ=<>A=ES+Oshw#3dv|N7RaU z3r8`SFl48NGH&V!o?i|G;Vs*(B=@IOH2)@$OXFR!tV^LI7fC1{^4&+FmF`R-@w6Qn z$Z_8UDR}X^W`81fG~&0 zdrc9x0;9wX+vAcjmO{^NFLL^8?wg2@*!;S*n|JS5;=ra^=)9jb?CAKX?L!Ld_eeav z7sfvDD`laWw~IFI7j%bM`m3y!fL*!eas-KA9`}T59Cu`ntnc$zsSf>uivocPmhMsq z)E*lC$J3P^mHTXU+;bu$M{HoV9`)v2Jdt>m za#gsk^(Y?Q7FB6_ZY1mOUSx`H;g+3hgvP5ZGeaIf^YZe>WgN)uP1{es`c;#nA2x>R zt9n=LVzNjcfWMA0rni|XPr7jxF0Xsn8bg+U3o*!aiqMo_uzl4p2}t* zh8CZc7M(DS^nK;Ym(=sVq&u=7S-+h`nQX{yl0J-HiLEb6QeH~a~B_%l)RlP8;d!(glj$S|FCgkcu$Ly?Z7lW{aKIMXl-RCS|_odJAlf)fdGL+ zW74$r-B{b{sVZsrF-&ZvQ~gU}Wbn`DLtNi5d^RgR$?cPn;c?Y)kF)cqTIkK9sN!+< zKj!=*Tw^`m5;<=t3rpj_Et#d@t7p+;UGo`PyvpR?u!*Se!-|E9u2-ZGV$O@g22`Ks z*=3@iJ9yX_7dJ(l_i--NpzHb1oQyM#axPXy$oDMw$CioB$_J(%%n2U?$yj?V(jhc* zGU}!`IS-qPfYtET36E>xAd#9lJHGB-CT!*ldaT3Wh` z3vwqvn#rRIvC6ML5yln=5cg{o*C}0?+;S5vO&UNd6tG?T{J0N zh%|=SOr@soBa&Q18YaF+0m01NOmH+c-_dHcvR;a`Fnn&kZJSUQ`zbH=W{Urd*L(i& zVL4u;ozm#$72BzjE=(9yirM}XemfRgp7X=0;{NpjV#qHZaUV_u@Y~=-MYooyN@&oI zAUa(8Ue`g5)rvkI!LeICvwG;mGM67Uxv;E>t3cnKbhpNR`<)>y8;Qq1)>E)>>3R)K zO}HB(9~kUf_o?(8`mpciFV*&Zx<7XT?!iWx190xAKVc-NL-|35m?VpP15R|A=sVbn z;5+?BThF!ncj57Y4HH{6bEE@hD4l^wW|2U7bOm_9m5}3nCaQpXy}Jf8V{+B=%{xY~ z$<=m*K+$a$aonW*mVbB04FjA~3M{Yb3| z%7$HKK0K(e_P8*&U1@wblFTUDtke}m`f@uU<4Ih!WTnM)DBJA|TS-2^@;BEm6CU6e zN35jr^@T1Ub`+65*xCxr;l-t=`~Rr&5xPEH4|wh*nQ_JPDHS*;IQH4jqM=Lm*Pf~B z#&?1Swr37S#3?cIBczHczI@^PL+D21G~+Ht3jWjRbMs`GKcpDymBeWmpB*3V2Dwqy z@|c<%92^ao#iDsr)OQ4J8@qgRzTu?Xa!^Syx%s$KQh)cG^XzV(>!|yJ*-t)f9hWG! zX?Sq7e@+vEo1*XXvsZ4C!L1o*wlI~PUBX4NJ4ZJ}uP=BgW`CcC#@l88_@nx_Nw@SP*cmzEBk)qI zXS&};na$}c+l?;r2M(Q?fSv&zv0igbPS6W3Q1(U6Wq~0RxtCvWne8s4`|stf9uW8z z6U&Rg7Ew`2N8>U0ghHK@PjW;Yn&iw!=l*3=27ixjwJJ*ZEc|Iz0aB2UR=1n!@7A$5 zlgf4?M@ffeU$Q8ssoBx%uOw5-WGzB;c?FI`ua&_92UFBXu* z_r-X15DeO{=5-r0UB5da-?60DjB&0E0`w!LB#}eVXpRunr#?X&(L`{FK`1hxrlvqd zO8F0uqTr2(q{&Z1+tFE1+5jS1hL*y^xfjbceyeu5XHRblNGS_RpwM%sZOZ3oi{AbO zS@wpx2?E9%ERGa2*yHx+)n7tKnTlOu-$a z0T~ayy^x6f-Y{e`@zMcQLe9p!%sa=(n%@WVMnTRDO{)=(-9srOj9i(_P(LBsAJEMq zBs!d>eE7bfDzY5$E(-@_gg2`?oJ-Dp+U83;2Xb$C@LCKy$7E=QEGo0*u4{CpbbI$W zDtquEATM_f?L3=~ch={TyX|A~wpyU8hV9dW@rLYPUQA(Q4p&#cN-Pv-RVwuS65+^T z6x`tq`%c;{UY7(ttNHS@3UV&nMHc#U477*V9PM>k+bUQ34jLH&$shf+G6Lq;-4Y1+ zBhJ)TAHN1wHQp~f_P20Jg~lAn&}zU_!&c6;9*n@Htds5OxhEc0&-m6JI?~U!AUZzG z8;!ZB9*>M_Lzgh-V!k0}2zh{JO&imc{I#-#M%?`c!PL)9u~8YPrW)j7Dt#GO%Le0u zFXsEp9Tr&;AKQe?%nTz{%Dk_6A)!Iyb9ClQGYniZ4x{SjG*@r2MIuxbwP!8E zuZ6`YiwZ4d$Iwx)la?!}iZgv1+8@T1@Oigc@1AZphdIpOYEg;kgQ6SE2C{DIF6P-m z%iZk|u_>gFIYqin@kIp8loz|=vEH#6r(oOmXV&R5^@p+>$A;y>n>(j@HT;{t#Lqx` zqy8;+bsUDwL>Fv9k$c|qCGi;kdp&KNtjhU1b=1_Y)ETK^C~gthqlck5qbT!_LsiGM zj)4fG=gl!=+i~j;R1*G0zYN4|ldW8s{io|rlGIK-g+LkhAneP)9R3?4;uF9KeL6>7x_3sg7lTmwdJ+T>E~CymXiG^ zehSG`IYOUwZ5@*tY5=4@As@tRzfOAIbNM0KZJ+Ya_a1?B)ov>PE&*kv!HRwb1ZlEe zDXyy5_AN5D-pei5GqCG4&6p6QHA9Ros5jL$U}^bdRh(sx!0s5_68su$IxtFSr=?wR zV64+4PYST~r-?}5dgoBBrAz=j(aG-n!9-h-*)vP`LpK2LX-*&y5m9%SK6l3}Ri?+Q zOEu#sm~iUz>Fgl$AO$unsPDU_!adho;n?;5kA_p;jfG&k2?3`Z{_E2*TA{tg){3?q z+vzP>t2IZUuZ1m-t}j1!Q0Eh?Q-s{zwR{@yk$&3Qg;pAeS1W_ospj}z80SgNS#s^3 zf#e_oF&}m`Zb?M#S1}KdM2eebGe+VyW{?v9=#{7omoA6h{pEiDN(NL<=kh@~5Pql& zft0~Loj(j=O`(1Dlen^@WN=*mtZKHG!zh(M!uEZ7}+$kwLm6&g5hL_uwMk3c8ok2i52Fi-Iisk|7n@k%Z`sk;@#3kv+`p zgfu^&l)AkEi#hcLuxKo=?!2x&g;o2kO5eh+e-sLi+Tk3;ugPBgLf{XKq>Pz37hwpG z_wBbO#}P(KL*J(>%_Sg)X|_EW|GaXUQat8ZZ^;7^A0qs#J06ES(iQ1U&lcd8(FGhz zd@*GuGQTGdRo~3#3U4;Ed~~tI?LB;>0&Xa&Z!`bxufPQ6pfkaXQ8w3vIi(HQ;ZMgV$(rKI;C3alLYgZq zlW$2+Cq-v_ge#AK?tcZ-U?quAS4#|Z2Vd-*v^edYcsQ9IA8MZ;abZT^Sf;;ouxXp7 z>u)wt)@jh0-%V$jYi1oD#1Z&rq$yXaqoH9Z8GOL!_k8zb)n^6!e5j-eg~T}Z{c<)@ zuD+{~l!n$+W=c^y_K$_=@w53&@yLl)i;2puF~KtGlIJf-A`u48yL}Rbpic!7(FxqC zJWk&)4;B>HJr62QC8I=$jFN9xmm;R$C?5d!fHlzI(RxSXGn8L=WR4yT6Gp+02afD- z)(}n`wWYv0X?=3Uzw0`1ArC2OZCZQ(RQS?4fF;j!_y^W6Bb$vbt~T`L&gSd_fp`}5 z-4cj#2NL$UnDb=djxe>AKVHr#He$JUe$y8KTm;8iWyzt(J87c=_u%{V9eHIeN(*+k zFTfJA7Vb_~cQo&>=(mb~`D+Vp)gvQz7wd^D$qahv0Jo*-W3%%4LiyqD3mUGlXN|pcg?1`N?J1K8D)q@V_30k zt0?ch|C7LcdGnr_ckuRX%WShZ{8>^>H_a@0K`gi-e>+NW3A-rU1hwY8OSB)lQqq1X zr3_B(`jvCt!*xD7<2ID4C{*1CG$K!Fuw0Vit!VRiK3Z3u*S8ndcA1N*HQl0831Z+J z5Go_5@p4WxkIr7VYg6#E#M2A>N?BUI-T0PSfp`B?%TeRXr}xeM20mBngydZI1_{X$ z_(zt>Cx9$vzRJ?Oe}zT+Z|u~ls#1k?!}78I?Tf@6VitO#VSeW!76Lg77|qGaxd@Cu z-O;q9)^D|AuyNK?o}Q<`iTPcR7%V4Fk$+r*AK zobBWAD6YbTZ}{wg5Rm||UArTDCPE1t_MIOSAZ+q zu1AO7Kxa~yi~Zu9VWzf2a>(O(|hVug2ZMgyN8j@%^v_m^qVc_oBn=kw3S*Tm-A{H)$!Vrj2x75I&pv;O7wr z3Wu6WJy{rd)Hs{UmVQ#DTx%j2J+AO~BWhTbgldSiGB75$r)P}5IgEVi)cbH|J7$Ct z>j+qs$Z})QG005R!5_1&j@G>k4tG~ zEY_D7S4o_+S&Iby{VgR%1NRD*3&@=ObZ_tSLS0{UXTPa!n*FQIwDlpvKMIevTO%$q zQ96-oDIY13TJai60!k(xRpG<*1VFN|fJj8XRQ@Ql#KuKWNVJd7aW|!FX-Nt9U^~QL zjq1%ohX^fMfVjkpA`N{?Y(T`XDv4+UdEHN4l3lCXTi0t%DGJtQSP6=h=yv;b9es>J zysn2dp~SAKdY=15zEeSV<~+j;TwxJj;zM{Gc39%l#skD{6C5w7=0>0A$wUQ@s;g~F zVa9&#uJ2BDw!)f?6`rr>k(d=ReN3@1Qqs8A)Gl(*p)%VcMTo?WeLozStE|1$9ue`i z`&JS1X#VqGAKb9~SthV@4s+54@=z1hm)=3uz<@~?)R3fs-ASp#X6@pZ;vU(enj8Q~}nfmgA340!Sw&`tg z-=iq;#;4W&Y!ml-scxmvOCr{8cDKzOG)#a%4^Bzp(8f}GY}LDfc0$cFKse#~V4ONQ zW-}2)pXa+h6~q#v1wam~(YjF@;8^~N`D_`EA|^dJYx z_y=OIyEDO4bBXa;Rb6135b0dgjjb~Hek|C$B|<1w3A+YB`SjtKOh18Omd1Pj(=U8e zWdj-JOY(HoI_g+O@Uw`@SVbBip}$-9zSnE#-{tRi38B0gw5w^a^hMHZFjoPhS$lrH z+tT@+HAC~W;gOn#MyFmHY$UyH($?pGPTY)*F|*;3!n8Y*xx>qKY!owWVWpbE`ZI=^ zPRx;j2xj`i!$`-{+r`YpxzXAd9_oss_Q#CA$Uv_2Bu(#{?S!s?y9-=+Y-~myW;(<6 zC11IMtiZ@a|uqK6HKJO&bZHlDB7lCUkb2z6oOJ1 z6drZ6Z$Wvv&zNZwL9y}lb>$u=NOgw7^-JXmaK-_VLPR$Z-T%B-|Zg?AFzu*Vfw84b%5CYGE;Gy(L>#>x8-$kNc_o9$v|b z9X)qWe-giaq>0E6GHO)yVq`RE*8;BYxd246U94q5*1APX8no|ab~@Cl|Iq*wOe(93 z17wNtQm(KegVnau7FC_u(p~hhM#5L+t)I6dh56p|0sZn2-S7JtW6#+S3pzV0>&Qzc zVrow86ByCkZQ2)mat7b;rYoM)nsUVp&imy9zD{{cFxPW!=36O|jg7fwq>_%(F{dz( z5$q*zEYYRlMA8QsMseriePP>jvkDZSE>XS{;WybG=i~c=$n>57AAM&2v9V?;>m(rJ zJpSQu%47Ifm&$s{oy8G74pWO`0VUnDjvAR0t%`Cd_pM1+z!HSfpmsk(mcwqk+4xMP zZlpHXq3`Wh{F0Qw=Li)dTbd*oBv(i4-A8<0=Mt>9V)GgDYR+DN>C9hqSM+9c!O$-$BBHzS0Pw5TfH)~vjkwu! zuyu^Cw2>15c9FrWoBO%|N&{afKVVYr&Zlc#T3EzfCjHjI+7YIV%SLTasU0jhz(@)M zh~n@3?d99gxp7@>C!O@c#$y}{V3!4buE* zN`!O8w(fLgB(*37a87alyUghuumQ3EZeWySMC8VJJd@}A2I?o9_fgTZ<7yrSvL;7I?WT@J2?yNrfA_E% zEUoV6#=JY0p*hK)*B?zdf}?AT?%UR)%?qeGtulZ>Unj<3uIs}T3F;e5=a5B)3&xl? z@B-;_cLn0E0mlF?K~woVT6jvIdDOP{hxty=+pzy()m4Vu`s$f2{^2=eA^ndHL%5% z$^W||p`3eW^4+^|Y`OuL-;-pIoUZGy$mr95cedwL2YW1DXFgUK_bMBJ=Z!fIytQy6 ztPD2&?|Dwhorw(|F4Yyqq2V+EnO`CF100;Pgn+zY{PzncZilA{`m|!D?HAc|W3|Xkr&@5QP@`|r6Gi?pw1a)OYBvL;qroQ^Pz@$2d_#FfkP{-a60 zzFdHC<*ODes8|jUt4RFB7GzRXmO=a9S+EEeYRzP6*@0U&<{Xi=)EW~|Z-W1wAy`ep z(z-PIdJa@EMkPv8Mibc~x$wQTJa#K>iFXJPj5O>h+5oE!2uQL6?EzK(cR=$<&C&{s ziELn5FV9~1LcZR&prFaO|DV*>cDnP3WPlpeu+j|yX2p7X-ms|FF*BbAodKAWCfGu{ zl*nD1W{z~&OvQs)=g_C$%imNY?Zz!`^P-=&@#sY`%w6d8`PvX658CRdicchW)oE%> zx@t4u73R=#vz|Z6Io$4-g6KnHa1$_jJ%W)_;|l>5EL#pu-mG%2d12gx)G{vCzK8o{ z=C~itldadJP&R6k4Lux?azU&T7Ow+(Z&IYn-D;Y$OML5qk@N4&4U@Be9V`0ru|0XTRsi!ltqF7&QYf;LKj_I&!EzSbEc*L=I)gP!t8mr?eM( z?78iPy674X9hLKjNE>H;f*2E3rrv@MdLN*lI!A0h88IO{b#tTVvD)q!FJwst;BhTb zhSorAIP{`TeXKV5kq-erWY^w2EyI0`w^Qcu;k&uEV9on$D1MVH)w~dM4T-syeUjFM zY2D*Cv0qy+=iOmJ?*l#MvcHM`GQ$t*A5Ua`Gd=@sOZ zXON|wztG)$+QHm2Q_j!wlP_v-O%&3hIi|MdMh^ax-_6hJ&gFqpE-u-aCq#b&c>NPDSr^ni>PH z>60x~cGRM@@RKI+Hu?(-cK8c-gIo)&fd z0Q;E`X9Tj4iHWg_IjmYfU@v*Id~=)R1z}9_6PIauq(8Nwezs$HF}QHTl-=rutl}n1 zm%pU+deOVD=rg<^lTkaPuaHtcAJZoVoRi+&xW7oX8)V)dFRc4IjM}mE6H~l6z8JB< z=7rpfVL3q_m}=g;WkzBi^nY}_SqV;9M$t9=7BExWiy=D*PiXrw*c7;y&iioZB6?c< zVZ@bH0QD+WJpI-eXP@kTM6x*%2J<|(3$u@vQi;R{@R!boDWWI zQP$^Y9xJ+z1_21Cm1_KfBoH1It%B5(G{g94(yLj-H8I_RtYVxZ+JcC6_S2bQz#sim zEIIez&Bd6{VVc7`2`xTb9!e=>zD(fx+PmG1k!e|G#^8W&&FB;ouka@UaEU_`GPjEV zUP>~oKSg5^5R4K0d!(q(ZV!eaWU@At>lWMb2$ZZ(z4M8ZlW~#_*pwEjM}lD0TpE|) z5o#xf94+tb1iyD)xcRa)*%|bqdk8Sb<0w0h8;BH-9A|DIaN@c$2KH8SKLCCxf=xHN zgEbJvw-J1(0IVn;9H)ZYTxetr7p4uBq6>a+KqT=G6784MLKJl!)jzEJsA`*IX_+TE ze$O>XwWCzyH!Jm46h|vfO(!o;H_%$kDe{LU03Z}87f85%7LuU6%XDG4nIH9)u=N1A zJ6lw~r0DN*Y2-7-icNE&wE6ee|@;*x;B=<)$}ml-FkZr) zpx|uEcGKO_G}jIQr=~xVJlu{jLl%#waEK62&U72QT(xh~Z7QuGJvGzcgL)?WfoNK~ z0KD&rgF}1fYhZKeIp(M~rV+HVyigtpaw_*e0o;Jbqsdkm8!sjgzi5v6>X*-n{15$& z9PEiuFd?ED;|mC+J;FbSA8T0-Q+7z30}Blz0L@R0tX_rk`KB~G1+l4xWEUEdL0rT ze+i8RA|$~P;;B% z$lQa35}AXQHhBVR$f+Z|sl^iLgW^B%4=A8dzzq1b#7zn{+9J;JN?wr;>vN zuEcu@w1d7|J^PNU^0Q!v5dXa>qWKX~%z|&r^;Ywzn@xD;wkRgwZ5Ar$fAyVi30O$g zDEN+e*`iQH27^xdP}#5FiAFBiV)jIu7?UnhJ&fG51h7`#j^bM#-`+6}97YMDN_CDr zJB_xVL~&aL@pkob>aF-=%Hw4!e5@g%w$!@KXmr_(b8#fHT|r`MB8gcz3d9UJL>U;e zUwwF#_4>M9>pMU4{Pw6%@FI=P+W+W`57n^AuskQ*Z&aQ@^T<6+Zxg!Po?;8&A( z?3UTfVu%fClR)Ff@+@&6rsFU3Qn#Z6STb(^QCBVIqn;Y>t)VaALJ;WUvLYBgWOqWZ3H@fsQarl|bz@Dy@2jZ@DI zG0V#2bCYi|abAISvs;4CnWDbyupu;Pdme-S%TkcFm~4aMCiKRQ@tkMHVa3AF{RsB+ z0(%Y_@7*e{2+;@7U@Ll!cc@dhZ>tw#e(KY!TYu!q^6%OmAmlhu6Jq+R_FC*{RF>*> zw{;Im07;LO`EJ0&-L8Zi;50_xI*UvZ=d@LQ8(-vFHvcnQdY!r|c$(IR({;tO@Ln9z z;M2L~ZwB|6^<)`EWCIEb55&HV#J>A^smFD}mEWYO?9Ths;>ds5(=9_PUKuB5C=RNtKCBGiRFgizCJ(}x$ePhplwNv9E+Qu#z!K~r~Z3<~z zqA^9naH-#{*>EksQTWX>H6oDYMY?V>%*mD;*!2E{DB%4>?Zx}eV6lJ6sMajPs0~Z% zK=5BPOB`Ly zBJ4VwnL`o7Ekfe==f2Brd*i<7 z!L7TGSikpj{2Jc|Aut+AJ&uG4LN}a9hNHqN0d7_!l_de0AB^_t3!=O`SPx({Xi*VA z0_AvTodXGz9pRYN%QwyTmK;+d021e1Ln)ExhN zXoR-RbJl5cL=l$QPp56FG7^hq>Y~rc`R9_m9*sc$7>*n)**%&z89J=mf+~6;4Sp^O z871a#YPD|^|2W%}Vu{$CrL4KGFw&+3$FbuYe1CN) zIs7L#?gD;qXp3l(7*LQSuDfr&yW37wJoNJJ_u>yV{%G~q?7Wr6T*N3wrZ=jV5K=3FwxT(WCBD%7kp;LKj7 z6vLd}#pnR25G+bkJ;CoN{^noCy1o(`U`>MomBQK^!q`r@u#3+Bi9e zm`?{?Y?bTm*ZXs)S9+(Y@#|!C7Z*Vg4g@B=C_ zL3!CC|8m)^fSMYLS_A~yM=Djc+W~S174XgL_b`gW&^%igbHaFVIW?K?89oZnJ2mAmn%RuEKh#heV?CTMfSyZq64$U}!eI*lKo5un{%(2TmydD6d~uHN zvfqPv9g$@+4?vq~lt`8seZkZ7sv|N=o zs__qrW1PDnTlk+GKPv2CuXTnkK<XDqYgtMwu|fMYh*5Ep?7}t@Fvc zemaK@fK`EgV|`F7_5z}!Aj?by%whxEW&kgxOj^Z24l_2bO;;fF4E$fMi2grUC_#$Mb$S-b z)^wo>ivWAwk?DKC&&l*WFgE&^ADkC459o=rm4NP~rJ_A7ZHu`pf1QePGK;U}$lekX_Pw_{ zKvz-xOL>Ah`A1e7Y^VuA_3>B88^p*v@6aD&EG!$fB{GUc0PZ{-Id2*scY@Wth5gJ8 z8<4Y_i}#m@ORD03|9qB0r^${n!?rdYNMSV;e7c;ewg~%Y+GXss0o{lVeMADliWZGs zo41IIkU7X_a3;wzcc{e(-di$8<-SVJ6)HS;incla{&K?)pb$o%N-h=cd3f5~$|QM1 zWuI8(FRfZM^4Z)&hED&NG?Djdmm~1qWw-jH{|W;5Uiybdg=x<_F0g&)okZvJz0Lol z>AmCGdjI$F+A)(D6{)f{zTH3!ZZ=O8n5WM`o9(;<3VV^f1rv=IKT}-dO z9r}O2!`BLFW1(h%@!zz*cb)eRp1ZE~a(s3D2)SnX;?|vmtxO)JXYra$idz5shMp+g za{bk5R6kbZIrWiTkJV@t;PHzhBHB}UCFEVGE({mhYd0HD3UuRm|M&X(q)?Qed7>Yn z^AX|RchVm{uWWFA(*!)m*M13_zjAYZ^Ofky`)p9-3y=@^zmLJlvV-%iouPj6^S$9= zeoU`-q4^@CcvPZ#xXF{2BPA<=MFypnkNG7}FY$+Ia>Sj@$?u;HAuXkk?^^@!1qJ-K zp_Uup!l%}Leu#6c|NH*`y^)9`ikE=cbKkY7kjMvp5ESh40GDT;3#3hEfd%wRQY%!K z8x3&Zz-#^x1(5^temoWZ)lOiP1k7J;JHYPP2{;hk1WqrP2LLvv0Je_NBId)52Twl> zU&2ToYO$-{;l~G?l9!DO7jj`!-_jOzDtm!fEKaq%7xiZGF}k`62%2C2T$Sh#$jV